Search code examples
pythonalgorithmecdsa

python ECDSA implementation miscalculation on big integers


I'm trying to implement ECDSA using python as part of my homework, I have a function named multiplication which takes two arguments Point P and t calculates B= tP.I have implemented this algorith based on iterative double and add algorithm on this wikipedia page the problem is when p coordination is small(one or two digits), the algorithm works fine but when coordination is large (about 70 digits) the result is different than what it supposed to be. here is the part of my code which calculates multiplication:

def addition(self, p, q):
    if p.is_infinite:
        return q
    elif q.is_infinite:
        return p
    else :
        if (q.x - p.x) == 0:
            point = Point.Point(0, 0)
            point.is_infinite = True
            return point
        s = int(((q.y - p.y) * Utils.Utils.mode_inverse(q.x - p.x, self.prime)) % self.prime)
    xr = int((math.pow(s, 2) - p.x - q.x) % self.prime)
    yr = int(((s * (p.x - xr)) - p.y) % self.prime)
    r = Point.Point(xr, yr)
    return r

def double(self, p):
    if p.is_infinite:
        return p
    if p.y == 0:
        point = Point.Point(0, 0)
        point.is_infinite = True
        return point
    s = int((((3 * math.pow(p.x, 2)) + self.a) * Utils.Utils.mode_inverse(2 * p.y, self.prime)) % self.prime)
    xr = int((math.pow(s, 2) - p.x - p.x) % self.prime)
    yr = int(((s * (p.x - xr)) - p.y) % self.prime)
    r = Point.Point(xr, yr)
    return r

def multiplication(self, p, t):
    bin_t = bin(t)[2:]
    Q = Point.Point(p.x, p.y)
    Q.is_infinite = True
    for i, digit in enumerate(bin_t):
        Q = self.double(Q)
        if digit == '1':
            Q = self.addition(Q, p)
    return Q

Here is my Util class:

class Utils(object):
    @staticmethod
    def mode_inverse(a, m):
        return pow(a, m - 2, m)

Here is my Point class:

class Point(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.is_infinite = False

I use Curve P-224 parameters which are:

p = 26959946667150639794667015087019630673557916260026308143510066298881

a = -3

b = 18958286285566608000408668544493926415504680968679321075787234672564

Gx = 19277929113566293071110308034699488026831934219452440156649784352033

Gy = 19926808758034470970197974370888749184205991990603949537637343198772

according to calculator http://www.christelbach.com/eccalculator.aspx I should get this result for calculating 2G:

Px = 11838696407187388799350957250141035264678915751356546206913969278886

Py = 2966624012289393637077209076615926844583158638456025172915528198331

but what I actually get is:

Px = 15364035107168693070617763393106849380516103015030577748254379737088

Py = 7033137909116168824469040716130881489351924269422358605872723100109

Is there any way to fix this?


Solution

  • This was just a guess:

    math.pow returns a floating point number (which has finite precision). I'd suggest using e.g. s.x * s.x instead of math.pow(s.x,2) in case the issue is hitting precision issues with bigger numbers.