math - Elliptic curve point addition over a finite field in Python -


in short, im trying add 2 points on elliptic curve y^2 = x^3 + ax + b on finite field fp. have working implementation on r, not know how alter general formulas ive found in order them sustain addition on fp.

when p not equal q, , z sum of p , q:

        dydx = (q.y - p.y)/(q.x - p.x)         z.x = dydx**2 - p.x - q.x         z.y = dydx * (z.x - p.x) + p.y 

when p equals q, again z sum:

        dydx = (3 * (p.x)**2 + self.a)/(2 * p.y)         z.x = dydx**2 - 2 * p.x         z.y = dydx * (z.x - p.x) + p.y 

these same formules found here. needs modified?

clarification: code above works elliptic curves on r. looking find needs changed work addition of points on finite field of order p.

there couple of issues here. first have wrong formulas: formulas negation of sum, or equivalently third point of curve lies on line through p , q. compare formula linked on wikipedia, , you'll see have z.y negation of value have.

a second issue formulas don't take origin account: if p inverse of q in group law, p + q origin, doesn't lie on affine part of curve , can't described pair of (x, y) coordinates. you'll need way specify origin.

let's write code. first need representation points on curve. use string 'origin' represent origin, , simple named tuple points on affine part of elliptic curve.

# create simple point class represent affine points. collections import namedtuple point = namedtuple("point", "x y")  # point @ infinity (origin group law). o = 'origin' 

for demonstration purposes, choose particular elliptic curve , prime. prime should greater 3 addition formulas valid. write function can use check particular point valid representation of point on curve. useful in checking didn't make mistakes in implementing addition formulas.

# choose particular curve , prime.  assume p > 3. p = 15733 = 1 b = 3  def valid(p):     """     determine whether have valid representation of point     on our curve.  assume x , y coordinates     reduced modulo p, can compare     2 points equality simple ==.     """     if p == o:         return true     else:         return (             (p.y**2 - (p.x**3 + a*p.x + b)) % p == 0 ,             0 <= p.x < p , 0 <= p.y < p) 

to divisions modulo p you'll need way compute inverses modulo p. simple , reasonably efficient trick here use python's three-argument variant of pow function: fermat's little theorem, pow(a, p-2, p) give inverse of a modulo p (provided of course that inverse exists - is, a not divisible p).

def inv_mod_p(x):     """     compute inverse x modulo p, assuming x     not divisible p.     """     if x % p == 0:         raise zerodivisionerror("impossible inverse")     return pow(x, p-2, p) 

and finally, here 2 functions compute negation , addition on elliptic curve. addition function based directly on formulas gave (after correcting sign of z.y), makes use of inv_mod_p perform divisions modulo p, , final reduction modulo p computed x , y coordinates.

def ec_inv(p):     """     inverse of point p on elliptic curve y^2 = x^3 + ax + b.     """     if p == o:         return p     return point(p.x, (-p.y)%p)  def ec_add(p, q):     """     sum of points p , q on elliptic curve y^2 = x^3 + ax + b.     """     if not (valid(p) , valid(q)):         raise valueerror("invalid inputs")      # deal special cases either p, q, or p + q     # origin.     if p == o:         result = q     elif q == o:         result = p     elif q == ec_inv(p):         result = o     else:         # cases not involving origin.         if p == q:             dydx = (3 * p.x**2 + a) * inv_mod_p(2 * p.y)         else:             dydx = (q.y - p.y) * inv_mod_p(q.x - p.x)         x = (dydx**2 - p.x - q.x) % p         y = (dydx * (p.x - x) - p.y) % p         result = point(x, y)      # above computations *should* have given point     # on curve.     assert valid(result)     return result 

we can check code above creating handful of points on curve , checking obey expected arithmetic laws.

p = point(6, 15) q = point(8, 1267) r = point(2, 3103) twop = ec_add(p, p) threep = ec_add(twop, p) # compute 4p 2 different ways. assert ec_add(p, threep) == ec_add(twop, twop) # check associative law. assert ec_add(p, ec_add(q, r)) == ec_add(ec_add(p, q), r) 

Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -