diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/ellipticcurve/math.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/ellipticcurve/math.py | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/ellipticcurve/math.py b/.venv/lib/python3.12/site-packages/ellipticcurve/math.py new file mode 100644 index 00000000..981ab4e7 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/ellipticcurve/math.py @@ -0,0 +1,181 @@ +from .point import Point + + +class Math: + + @classmethod + def modularSquareRoot(cls, value, prime): + return pow(value, (prime + 1) // 4, prime) + + @classmethod + def multiply(cls, p, n, N, A, P): + """ + Fast way to multily point and scalar in elliptic curves + + :param p: First Point to mutiply + :param n: Scalar to mutiply + :param N: Order of the elliptic curve + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point that represents the sum of First and Second Point + """ + return cls._fromJacobian( + cls._jacobianMultiply(cls._toJacobian(p), n, N, A, P), P + ) + + @classmethod + def add(cls, p, q, A, P): + """ + Fast way to add two points in elliptic curves + + :param p: First Point you want to add + :param q: Second Point you want to add + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point that represents the sum of First and Second Point + """ + return cls._fromJacobian( + cls._jacobianAdd(cls._toJacobian(p), cls._toJacobian(q), A, P), P, + ) + + @classmethod + def inv(cls, x, n): + """ + Extended Euclidean Algorithm. It's the 'division' in elliptic curves + + :param x: Divisor + :param n: Mod for division + :return: Value representing the division + """ + if x == 0: + return 0 + + lm = 1 + hm = 0 + low = x % n + high = n + + while low > 1: + r = high // low + nm = hm - lm * r + nw = high - low * r + high = low + hm = lm + low = nw + lm = nm + + return lm % n + + @classmethod + def _toJacobian(cls, p): + """ + Convert point to Jacobian coordinates + + :param p: First Point you want to add + :return: Point in Jacobian coordinates + """ + return Point(p.x, p.y, 1) + + @classmethod + def _fromJacobian(cls, p, P): + """ + Convert point back from Jacobian coordinates + + :param p: First Point you want to add + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point in default coordinates + """ + z = cls.inv(p.z, P) + x = (p.x * z ** 2) % P + y = (p.y * z ** 3) % P + + return Point(x, y, 0) + + @classmethod + def _jacobianDouble(cls, p, A, P): + """ + Double a point in elliptic curves + + :param p: Point you want to double + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point that represents the sum of First and Second Point + """ + if p.y == 0: + return Point(0, 0, 0) + + ysq = (p.y ** 2) % P + S = (4 * p.x * ysq) % P + M = (3 * p.x ** 2 + A * p.z ** 4) % P + nx = (M**2 - 2 * S) % P + ny = (M * (S - nx) - 8 * ysq ** 2) % P + nz = (2 * p.y * p.z) % P + + return Point(nx, ny, nz) + + @classmethod + def _jacobianAdd(cls, p, q, A, P): + """ + Add two points in elliptic curves + + :param p: First Point you want to add + :param q: Second Point you want to add + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point that represents the sum of First and Second Point + """ + if p.y == 0: + return q + if q.y == 0: + return p + + U1 = (p.x * q.z ** 2) % P + U2 = (q.x * p.z ** 2) % P + S1 = (p.y * q.z ** 3) % P + S2 = (q.y * p.z ** 3) % P + + if U1 == U2: + if S1 != S2: + return Point(0, 0, 1) + return cls._jacobianDouble(p, A, P) + + H = U2 - U1 + R = S2 - S1 + H2 = (H * H) % P + H3 = (H * H2) % P + U1H2 = (U1 * H2) % P + nx = (R ** 2 - H3 - 2 * U1H2) % P + ny = (R * (U1H2 - nx) - S1 * H3) % P + nz = (H * p.z * q.z) % P + + return Point(nx, ny, nz) + + @classmethod + def _jacobianMultiply(cls, p, n, N, A, P): + """ + Multily point and scalar in elliptic curves + + :param p: First Point to mutiply + :param n: Scalar to mutiply + :param N: Order of the elliptic curve + :param P: Prime number in the module of the equation Y^2 = X^3 + A*X + B (mod p) + :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p) + :return: Point that represents the sum of First and Second Point + """ + if p.y == 0 or n == 0: + return Point(0, 0, 1) + + if n == 1: + return p + + if n < 0 or n >= N: + return cls._jacobianMultiply(p, n % N, N, A, P) + + if (n % 2) == 0: + return cls._jacobianDouble( + cls._jacobianMultiply(p, n // 2, N, A, P), A, P + ) + + return cls._jacobianAdd( + cls._jacobianDouble(cls._jacobianMultiply(p, n // 2, N, A, P), A, P), p, A, P + ) |