An elliptic curve is a plane curve defined by an equation of the form:
y2=x3+ax+b
after a linear change of variables (a and b are real numbers). This type of equation is called a Weierstrass equation.
The definition of elliptic curve also requires that the curve is non-singular. Geometrically, this means that the graph has no cusps, self-intersections, or isolated points. Algebraically, this holds if and only if the discriminant:
Δ=−16(4a3+27b2)
is not equal to zero. (Although the factor −16 is irrelevant to whether or not the curve is non-singular, this definition of the discriminant is useful in a more advanced study of elliptic curves.)
The (real) graph of a non-singular curve has two components if its discriminant is positive, and one component if it is negative. For example, in the graphs shown in figure below, the discriminant in the first case is 64, and in the second case is −368:
Arithmetics on Elliptic Curves
Point Negation
Algorithm
The rule is: if P=(xP,yP), then P+(xP,xP+yP)=O. In other word, −P=(xP,xP+yP).
Implementation
In this challenge we are given P=(8045,6936), hence Q=−P=(8045,(8045+6936)mod9739)=(8045,2803)
Point Addition
Algorithm
If P=O, then P+Q=Q.
Otherwise, if Q=O, then P+Q=P.
Otherwise, write P=(x1,y1) and Q=(x2,y2).
If x1=x2 and y1=−y2, then P+Q=O.
Otherwise:
if P=Q: λ=(y2−y1)/(x2−x1)
if P=Q: λ=(3x12+a)/2y1
x3=λ2−x1−x2 and y3=λ(x1−x3)−y1
P+Q=(x3,y3)
Implementation
#!/usr/bin/env python3from Crypto.Util.number import inverse#--------Data--------#a =497b =1768p =9739P = (493,5564)Q = (1539,4742) R = (4403,5202)#--------Addition--------#defpoint_addition(P,Q):# Define zero O = (0,0)# If P = O, then P + Q = Qif P == O:return Q# If Q = O, then P + Q = Pif Q == O:return P# Otherwise, write P = (x1, y1) and Q = (x2, y2) x1, y1 = P[0], P[1] x2, y2 = Q[0], Q[1]# If x1 = x2 and y1 = -y2, then P + Q = Oif x1 == x2 and y1 ==-y2:return O# Otherwise, if P ≠ Q: λ = (y2 - y1) / (x2 - x1)if P != Q: lam = ((y2 - y1) *inverse(x2 - x1, p)) % p# If P = Q: λ = (3 * x1**2 + a) / 2 * y1else: lam = ((3* x1**2+ a) *inverse(2* y1, p)) % p# x3 = λ**2 - x1 - x2, y3 = λ *( x1 - x3) - y1 x3 = (lam**2- x1 - x2) % p y3 = (lam * (x1 - x3) - y1) % p# P + Q = (x3, y3) summation = (x3, y3)return summation#--------Testing--------## X = (5274, 2841) # Y = (8669, 740)# print(point_addition(X, Y))# print(point_addition(X, X))# S = P + P + Q + RS =point_addition(point_addition(point_addition(P, P), Q), R)print(S)
Scalar Multiplication
Algorithm
Input: P in E(Fp) and an integer n>0.
Set Q=P and R=O.
Loop while n>0.
If n≡1mod2, set R=R+Q.
Set Q=2Q and n=⌊n/2⌋.
If n>0, continue with loop at Step 2.
Return the point R, which equals nP.
Implementation
#!/usr/bin/env python3from Crypto.Util.number import inverse#--------Data--------#a =497b =1768p =9739P = (2339,2213)#--------Functions--------#defpoint_addition(P,Q):# Define zero O = (0,0)# If P = O, then P + Q = Qif P == O:return Q# If Q = O, then P + Q = Pif Q == O:return P# Otherwise, write P = (x1, y1) and Q = (x2, y2) x1, y1 = P[0], P[1] x2, y2 = Q[0], Q[1]# If x1 = x2 and y1 = -y2, then P + Q = Oif x1 == x2 and y1 ==-y2:return O# Otherwise, if P ≠ Q: λ = (y2 - y1) / (x2 - x1)if P != Q: lam = ((y2 - y1) *inverse(x2 - x1, p)) % p# If P = Q: λ = (3 * x1**2 + a) / 2 * y1else: lam = ((3* x1**2+ a) *inverse(2* y1, p)) % p# x3 = λ**2 - x1 - x2, y3 = λ *( x1 - x3) - y1 x3 = (lam**2- x1 - x2) % p y3 = (lam * (x1 - x3) - y1) % p# P + Q = (x3, y3) summation = (x3, y3)return summationdefscalar_multiplication(n,P):# Define zero O = (0,0)# Set Q = P and R = O Q, R = P, Owhile n >0:# If n ≡ 1 mod 2, set R = R + Qif n %2==1: R =point_addition(R, Q)# Set Q = 2 Q and n = ⌊n/2⌋. Q =point_addition(Q, Q) n //=2return R#--------Testing--------## X = (5323, 5438)# print(scalar_multiplication(1337, X))# Q = 7863 Pprint(scalar_multiplication(7863, P))
Curves and Logs
Algorithm
Alice and Bob agree on a curve E, a prime p and a generator point G.
Alice generates a secret random integer nA and calculates QA=nAG.
Bob generates a secret random integer nB and calculates QB=nBG.
Alice sends Bob QA, and Bob sends Alice $$Q_B$$. Due to the hardness of ECDLP, an onlooker Eve is unable to calculatenA/B in reasonable time.
Alice then calculates nAQB, and Bob calculates nBQA.
Due to the associativity of scalar multiplication, S=nAQB=nBQA. Alice and Bob can use S as their shared secret.
Implementation
#!/usr/bin/env python3from Crypto.Util.number import inversefrom hashlib import sha1#--------Data--------#a =497b =1768p =9739G = (1804,5368)Q_A = (815,3190)n_B =1829#--------Functions--------#defpoint_addition(P,Q):# Define zero O = (0,0)# If P = O, then P + Q = Qif P == O:return Q# If Q = O, then P + Q = Pif Q == O:return P# Otherwise, write P = (x1, y1) and Q = (x2, y2) x1, y1 = P[0], P[1] x2, y2 = Q[0], Q[1]# If x1 = x2 and y1 = -y2, then P + Q = Oif x1 == x2 and y1 ==-y2:return O# Otherwise, if P ≠ Q: λ = (y2 - y1) / (x2 - x1)if P != Q: lam = ((y2 - y1) *inverse(x2 - x1, p)) % p# If P = Q: λ = (3 * x1**2 + a) / 2 * y1else: lam = ((3* x1**2+ a) *inverse(2* y1, p)) % p# x3 = λ**2 - x1 - x2, y3 = λ *( x1 - x3) - y1 x3 = (lam**2- x1 - x2) % p y3 = (lam * (x1 - x3) - y1) % p# P + Q = (x3, y3) summation = (x3, y3)return summationdefscalar_multiplication(n,P):# Define zero O = (0,0)# Set Q = P and R = O Q, R = P, O# Loop while n > 0while n >0:# If n ≡ 1 mod 2, set R = R + Qif n %2==1: R =point_addition(R, Q)# Set Q = 2 Q and n = ⌊n/2⌋. Q =point_addition(Q, Q) n //=2return R#--------ECDH--------#S =scalar_multiplication(n_B, Q_A)key =sha1(str(S[0]).encode()).hexdigest()print(key)