Add Elliptic Curve and docs
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from Cryptotools.Groups.elliptic import Point
|
||||
import numpy as np
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class Curve:
|
||||
# Curve
|
||||
WEIERSTRASS = 0
|
||||
MONTGOMERY = 1
|
||||
|
||||
|
||||
def __init__(self, a, b, t):
|
||||
self._a = a
|
||||
self._b = b
|
||||
|
||||
if t not in (Curve.WEIERSTRASS, Curve.MONTGOMERY):
|
||||
raise Exception(f"The type of the curve is not recognized")
|
||||
|
||||
self._type = t
|
||||
self._xtmp = np.linspace(-5, 5, 500).tolist()
|
||||
self._x = list()
|
||||
self._y = list()
|
||||
self._yn = list()
|
||||
self._points = list()
|
||||
self._pointsSym = list()
|
||||
|
||||
def f(self, x):
|
||||
if self._type == Curve.WEIERSTRASS:
|
||||
y = pow(x, 3) + (self._a * x) + self._b
|
||||
if self._type == Curve.MONTGOMERY:
|
||||
y = pow(x, 3) + (3 * pow(x, 2)) + x
|
||||
if y > 0:
|
||||
return sqrt(y)
|
||||
return None
|
||||
|
||||
def generatePoints(self):
|
||||
for x in self._xtmp:
|
||||
y = self.f(x)
|
||||
if y is None:
|
||||
continue
|
||||
|
||||
self._x.append(x)
|
||||
self._y.append(y)
|
||||
self._yn.append(-y)
|
||||
self._points.append(Point(
|
||||
x,
|
||||
y
|
||||
))
|
||||
self._pointsSym.append(Point(
|
||||
x,
|
||||
-y
|
||||
))
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._x
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._y
|
||||
|
||||
@property
|
||||
def yn(self):
|
||||
return self._yn
|
||||
|
||||
def getPoints(self):
|
||||
return self._points
|
||||
|
||||
def getPointsSym(self):
|
||||
return self._pointsSym
|
||||
|
||||
def add(self, P, Q) -> Point:
|
||||
"""
|
||||
This function operathe addition operation on two points P and Q
|
||||
|
||||
Args:
|
||||
P (Object): The first Point on the curve
|
||||
Q (Object): The second Point on the curve
|
||||
|
||||
Returns:
|
||||
Return the Point object R
|
||||
"""
|
||||
|
||||
## Check if P or Q are infinity
|
||||
if (P.x, P.y) == (0, 0) and (Q.x, Q.y) == (0, 0):
|
||||
return Point(0, 0)
|
||||
elif (P.x, P.y) == (0, 0):
|
||||
return Point(Q.x, Q.y)
|
||||
elif (Q.x, Q.y) == (0, 0):
|
||||
return Point(P.x, P.y)
|
||||
|
||||
# point doubling
|
||||
if P.x == Q.x:
|
||||
# Infinity
|
||||
if P.y != Q.y or Q.y == 0:
|
||||
return Point(0, 0)
|
||||
|
||||
# Point doubling
|
||||
try:
|
||||
inv = pow(2 * P.y, -1); # It's working with the inverse modular, WHY ???
|
||||
m = ((3 * pow(P.x, 2)) + self._a) * inv
|
||||
except ValueError:
|
||||
return Point(0, 0)
|
||||
|
||||
else:
|
||||
try:
|
||||
inv = pow(Q.x - P.x, -1)
|
||||
m = (Q.y - P.y) * inv
|
||||
except ValueError:
|
||||
# May call this Exception: base is not invertible for the given modulus
|
||||
# I return an Infinity point until I fixed that
|
||||
return Point(0, 0)
|
||||
|
||||
xr = (pow(m, 2) - P.x - Q.x)
|
||||
|
||||
yr = (m * (P.x - xr)) - P.y
|
||||
return Point(xr, yr)
|
||||
|
||||
def scalar(self, P, n) -> Point:
|
||||
"""
|
||||
This function compute a Scalar Multiplication of P, n time. This algorithm is also known as Double and Add.
|
||||
|
||||
Args:
|
||||
P (point): the Point to multiplication
|
||||
n (Integer): multiplicate n time P
|
||||
|
||||
Returns:
|
||||
Return the result of the Scalar multiplication
|
||||
"""
|
||||
binary = bin(n)[2:]
|
||||
binary = binary[::-1] # We need to reverse the binary
|
||||
|
||||
nP = Point(0, 0)
|
||||
Rtmp = P
|
||||
|
||||
for b in binary:
|
||||
if b == '1':
|
||||
nP = self.add(nP, Rtmp)
|
||||
Rtmp = self.add(Rtmp, Rtmp) # Double P
|
||||
|
||||
return nP
|
||||
|
||||
def find_reverse(self, P):
|
||||
"""
|
||||
This function return the reverse of the Point P
|
||||
Args:
|
||||
P (Point): Point object to find
|
||||
|
||||
Returns:
|
||||
Return the object Pr, which is the reverse point of P
|
||||
"""
|
||||
Pr = None
|
||||
for p in self._pointsSym:
|
||||
if P.x == p.x and -P.y == p.y:
|
||||
Pr = Point(p.x, p.y)
|
||||
break
|
||||
return Pr
|
||||
Reference in New Issue
Block a user