def madd(p1,p2,A,B,p): """Adds p1 and p2 on a Montgomery curve""" if B*(A**2 - 4) == 0 % p: #checks Montgomery requirements print("Singular Curve") return if math.isinf(p1[0]) and math.isinf(p2[0]): return math.inf,1 #O + O = O if math.isinf(p1[0]): return p2 #O + p2 = p2 if math.isinf(p2[0]): return p1 #p1 + O = p1 else: x1,y1 = p1 #assigns coordinates x2,y2 = p2 #assigns coordinates if B*y1**2 % p != (x1**3 + A*x1**2 + x1) % p: #checks if point is on curve return False #otherwise reject if B*y2**2 % p != (x2**3 + A*x2**2 + x2) % p: #checks if point is on curve return False #otherwise reject if x1==x2 and -y2 % p == y1: return math.inf,1 #(x1,y1) + (x1,-y1) = O elif x1==x2: #point doubling sl = ((3 * x1**2 + 2*A*x1 + 1)*mminv(2*B*y1,p)) % p #slope x = (B*(sl**2) - 2*x1 - A) % p return x, (sl*(x1 - x) - y1) % p else: #point addition sl = (y2-y1)*mminv(x2-x1,p) % p #slope x = (B*(sl**2) - x1 - x2 - A) % p return x, (sl*(x1 - x) - y1) % p
def w2check(a, b, p): """Checks for point of order two on WNF curve""" """Returns x coordinate alpha if exists""" dis = -16 * (4 * a**3 + 27 * b**2) % p #calculates discriminant ldis = legendres(dis, p) #finds Legendre Symbol of discriminant if dis == 0: print("Discriminant = 0") #rejects if discriminant is 0 return if ldis % 2 == 1: #1 root if -1, 3 if 1, doing both cases here r = ((b**2) * mminv(4, p) + (a**3) * mminv(27, p)) % p #using cubic formulae rt = modroot(r, p) #sqrt of r if not rt: print( "No transformation") #if sqrt does not exist, no alpha exists return else: rt = rt[0] #assign one root to use in algebra bf = -b * mminv(2, p) % p #cubic formulae alpha = (modcube(bf + rt, p) + modcube(bf - rt, p)) #cubic formulae if (alpha**3 + a * alpha + b) % p == 0: return alpha % p #double checking value of alpha else: print("error") #reject otherwise, output alpha for error checking return alpha % p else: print("No point of order two") return
def wadd(p1,p2,a,b,p): """Adds p1 and p2 on a WNF curve""" if math.isinf(p1[0]) and math.isinf(p2[0]): return math.inf,1 #O + O = O if math.isinf(p1[0]): return p2 #O + p2 = p2 if math.isinf(p2[0]): return p1 #p1 + O = p1 else: x1,y1 = p1 #assigns coordinates x2,y2 = p2 #assigns coordinates if y1**2 % p != (x1**3 + a*x1 + b) % p: #checks if point is on curve return False #otherwise reject if y2**2 % p != (x2**3 + a*x2 + b) % p: #checks if point is on curve return False #otherwise reject if x1==x2 and -y2 % p == y1: return math.inf,1 #(x1,y1) + (x1,-y1) = O elif x1==x2: #point doubling sl = ((3 * x1**2 + a)*mminv(2*y1,p)) % p #slope x = (sl**2 - x1 - x2) % p return x, -(sl * (x - x1) + y1) % p else: #point addition sl = (y2-y1)*mminv(x2-x1,p) % p #slope x = (sl**2 - x1 - x2) % p return x, -(sl * (x - x1) + y1) % p
def pmtoe(p1, A, B, p): """Transforms a Montgomery point to a twisted Edwards point""" start = time.process_time() * 1000 if A < 3 % p and A > -2 % p: #checks requirements on A for curve mapping print("A in {-2,2}") #if fails, reject return False elif B == 0 % p: #checks requirements on B for curve mapping print("B = 0") #if fails, reject return False x1, y1 = p1 #assigns coordinates if math.isinf(x1): return 0, 1 #inf -> (0,1) if B * y1**2 % p != (x1**3 + A * x1**2 + x1) % p: #checks if point is on curve return False #otherwise reject #exceptional points elif y1 == 0 % p: print(y1) if x1 == 0 % p: return 0, -1 % p #(0,0) -> (0,-1) elif 2 * x1 % p == (-A + modroot((A + 2) * (A - 2), p)[0]) % p: return math.inf, 2 #point of order two on M -> inf ('positive' root) elif 2 * x1 % p == (-A - modroot((A + 2) * (A - 2), p)[0]) % p: return math.inf, -2 #point of order two on M -> inf ('negative' root) else: return elif x1 == -1 % p: if y1 == modroot((A - 2) * mminv(B, p), p): return math.inf, 4 #point of order four on M -> inf ('positive' root) elif y1 == -modroot((A - 2) * mminv(B, p), p) % p: return math.inf, -4 #point of order four on M -> inf ('negative' root) #general points else: print(time.process_time() * 1000 - start) return x1 * mminv(y1, p) % p, (x1 - 1) * mminv(x1 + 1, p) % p
def petow(p1, a, d, p): """Transforms a twisted Edwards point to a Weierstrass point""" if a == d: #checks curve mapping requirements print("a=d") #if fails, reject return elif a == 0 or d == 0: print("Must be non zero") return x1, y1 = p1 #assigns coordinates #exceptional points if math.isinf(x1): #computes inf seperately, since may be (inf,4) or (inf,2) p2 = petom(p1, a, d, p) #computes point at infinity -> point on montgomery A, B = (2 * (a + d) * mminv(a - d, p)) % p, ( 4 * mminv(a - d, p)) % p #calculates A and B p3 = pmtow(p2, A, B, p) #computes point on montgomery -> point on W return p3 if (a * x1**2 + y1**2) % p != (1 + d * (x1**2) * (y1**2)) % p: #checks point is on curve return False #otherwise reject elif x1 % p == 0 and y1 % p == 1: return math.inf, 1 #(0,1) -> inf -> inf else: p2 = petom(p1, a, d, p) #computes point on Montgomery A, B = (2 * (a + d) * mminv(a - d, p)) % p, ( 4 * mminv(a - d, p)) % p #calculates A and B p3 = pmtow(p2, A, B, p) #computes point on W return p3
def mtow(A, B, p): """Converts Montgomery curve to WNF""" #conversion always exists - no need to check start = time.process_time() * 1000 a = ((3 - A**2) * mminv(3 * B**2, p)) % p #calculates a b = ((2 * A**3 - 9 * A) * mminv(27 * B**3, p)) % p #calculates b print("y**2 = x**3 + ", a, "x +", b) #prints curve equation print("An Isomorphism!") #all existing W to M mappings are isomorphisms print(time.process_time() * 1000 - start) return a, b
def pmtow(p1, A, B, p): """Transforms a Montgomery point to a Weierstrass point""" start = time.process_time() * 1000 x1, y1 = p1 #assigns coordinates if B * y1**2 % p != (x1**3 + A * x1**2 + x1) % p: #checks if point is on curve return False #otherwise reject #exceptional points if math.isinf(x1): print(time.process_time() * 1000 - start) return math.inf, 1 #inf -> inf #general points else: print(time.process_time() * 1000 - start) return (x1 * mminv(B, p) + A * mminv(3 * B, p)) % p, y1 * mminv(B, p) % p
def etom(a, d, p): """Converts twisted Edwards to Montgomery""" """Checks for conversion""" #start = time.process_time() *1000 if a == d: #checks parameters distinct print("a=d") #otherwise reject return elif a == 0 or d == 0: #checks parameters non zero print("Must be non zero") #otherwise reject return A = (2 * (a + d) * mminv(a - d, p)) % p #calculates A B = (4 * mminv(a - d, p)) % p #calculates B print(B, "y**2 = x**3 +", A, "x**2 + x") #prints curve equation if legendres(a, p) == legendres(d, p): print("Not an Isomorphism :(" ) #not isomorphic if a & d both square/not square elif legendres(a, p) == 1: print("An Isomorphism!") #isomorphic if a square, d not square #print(time.process_time()*1000 - start) return A, B
def mtoe(A, B, p): """Converts Montgomery curve to twisted Edwards""" """Checks for conversion""" #start = time.process_time()*1000 if A < 3 % p and A > -2 % p: #checks requirement of A print("A in {-2,2}") #if fails, reject return elif B == 0 % p: #checks B non zero print("B = 0") #otherwise reject return a = ((A + 2) * mminv(B, p)) % p #calculates a d = ((A - 2) * mminv(B, p)) % p # calculates d print(a, "x**2 + y**2 = 1 + ", d, "x**2y**2") #prints curve equation if legendres(a, p) == legendres(d, p): print("Not an Isomorphism :(" ) #not isomorphic if a & d both square/not square elif legendres(a, p) == 1: print("An Isomorphism!") #isomorphic if a square, d not square elif legendres(a, p) == -1: print("Not an Isomorphism :(") #not isomorphic if a not square # print(time.process_time()*1000 - start) return a, d
def eadd(p1,p2,a,d,p): """ Adds p1 and p2 on a twsited Edwards curve We assume that there exists a pt of order 4, so identity is (0,1) """ if d*(1 - d) == 0 % p: #checks Edwards requirements print("Singular Curve") return x1,y1 = p1 x2,y2 = p2 #check if in curve here if (a*x1**2 + y1**2) % p != (1 + d*(x1**2)*(y1**2)) % p: #checks point is on the curve return False #otherwise reject if (a*x2**2 + y2**2) % p != (1 + d*(x2**2)*(y2**2)) % p: #checks point is on the curve return False #otherwise reject if p1 == (0,1) and p2 == (0,1): return 0,1 #O + O = O if p1 == (0,1): return p2 #O + p2 = p2 if p2 == (0,1): return p1 #p1 + O = p2 if y1==y2 and -x2 % p == x1: #(x1, y1) + (-x1, y1) = O return 0,1 else: #point addition dxy = d*x1*x2*y1*y2 % p return (x1*y2 + y1*x2)*mminv(1+dxy,p) % p, (y1*y2 - a*x1*x2)*mminv(1-dxy,p) % p
def petom(p1, a, d, p): """Transforms a twisted Edwards point to a Montgomery point""" if a == d: #checks curve mapping requirements print("a=d") #if fails, reject return False elif a == 0 or d == 0: print("Must be non zero") return False x1, y1 = p1 #assigns coordinates #exceptional points if math.isinf(x1): A = (2 * (a + d) * mminv(a - d, p)) % p #calculates A B = (4 * mminv(a - d, p)) % p #calculates B if y1 % p == 2: x = (-A + modroot((A + 2) * (A - 2), p)[0]) * mminv( 2, p) % p #point of order two on M ('positive' root) return x, 0 elif y1 % p == -2 % p: x = (-A - modroot((A + 2) * (A - 2), p)[0]) * mminv( 2, p) % p #point of order two on M ('negative' root) return x, 0 elif y1 % p == 4: y = modroot((A - 2) * mminv(B, p), p) #point of order four on M ('positive' root) return -1, y elif y1 % p == -4 % p: y = -modroot((A - 2) * mminv(B, p), p) % p #point of order four on M ('negative' root) return -1, y else: return #no other points at infinity should exist on a twisted Edwards curve if (a * x1**2 + y1**2) % p != (1 + d * (x1**2) * (y1**2)) % p: #checks point is on the curve return False #otherwise reject elif x1 % p == 0 and y1 % p == 1: return math.inf, 1 #(0,1) -> inf elif x1 % p == 0 and y1 % p == -1 % p: return 0, 0 #(0,-1) -> (0,0) #general points else: return (1 + y1) * mminv(1 - y1, p) % p, (1 + y1) * mminv( x1 * (1 - y1), p) % p
def wtom(a, b, p): """Converts WNF curve to Montgomery""" """Checks for conversion""" start = time.process_time() * 1000 alpha = w2check(a, b, p) #finds point of order two on W if not alpha: print("No conversion") #if no such point, reject return else: if not modroot(3 * alpha**2 + a, p): #checks if square root exists print("No conversion") #otherwise, reject return B = mminv(max(modroot(3 * alpha**2 + a, p)), p) #calulates B A = 3 * alpha * B % p #calulates A print(B, "y**2 = x**3 +", A, "x**2 + x") #prints curve equation print( "An Isomorphism!") #all existing W to M mappings are isomorphisms print(time.process_time() * 1000 - start) return A, B, alpha
def pwtom(p1, a, b, p, A, B): """Transforms a Weierstrass point to a Montgomery point""" x1, y1 = p1 #assigns coordinates if math.isinf(p1[0]): return math.inf, 1 #inf -> inf if y1**2 % p != (x1**3 + a * x1 + b) % p: #checks if point is on curve return False #otherwise reject if not A: #if user does not input A, calulates it s, alpha = wtom(a, b, p)[1], wtom(a, b, p)[2] #finds B, alpha from wtom if not alpha: #checks if a point of order two exists print("No conversion") #otherwise reject return else: alpha = A * mminv(3 * B, p) % p #if user inputs A,B calculate alpha from them s = B #as above #exceptional points if p1 == (alpha, 0): return 0, 0 #if point has order two, map to 0,0 #general points else: return s * (x1 - alpha) % p, s * y1 % p