#!/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