2024-04-25 19:03:35 +02:00

116 lines
3.0 KiB
Python

from util import Object
import numpy as np
# XXX: remove this
import libnum
CURVE_LINSPACE_OFFSET = 10
CURVE_LINSPACE_NUM = 2000
# NOTE: ADD NEW CURVES HERE
# this way they are automatically added to the gui
DEFAULT_CURVES = {
'Default': (3, 3, 11),
'secp384r1 (NSA backdoor)': (3, 0, 2**384 - 2**128 - 2**96 + 2**32 - 1),
'secp256k1 (BTC)': (0, 7, 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1),
}
def line_slope(x1, y1, x2, y2):
return (y2 - y1) / (x2 - x1)
def intersection(x1, y1, x2, y2, x3, y3, x4, y4):
s1 = line_slope(x1, y1, x2, y2)
s2 = line_slope(x3, y3, x4, y4)
if s1 == s2:
raise Exception("passed lines are paralel")
c1 = y1 - s1 * x1
c2 = y3 - s2 * x3
x = (c2 - c1) / (s1 - s2)
y = s1 * x + c1
return x, y
class EllipticCurve(Object):
def __init__(self, a, b):
self.a = a
self.b = b
self._points()
def _points(self):
def iterih_square(x):
return (x**3) + (self.a * x**2) + self.b
start = 0
step = 0.1
while True:
if iterih_square(start) < 0: break
else: start -= step
self.pp = np.empty((2, CURVE_LINSPACE_NUM))
self.np = np.empty((2, CURVE_LINSPACE_NUM))
for i, xi in enumerate(np.linspace(start, start + CURVE_LINSPACE_OFFSET, CURVE_LINSPACE_NUM)):
t = np.sqrt(iterih_square(xi))
self.pp[0][i] = xi
self.pp[1][i] = t
self.np[0][i] = xi
self.np[1][i] = -t
def points(self):
return np.concatenate((self.pp, self.np), axis=0)
def _cord_slope(self, x1, y1, x2, y2):
return (y2 - y1) / (x2 - x1)
def _tangent_slope(self, x, y):
return (3 * x**2 + self.a) / (2 * y)
def _add(self, s, x1, y1, x2, y2):
x = s**2 - x1 - x2
y = s * (x1 - x) - y1
return (x, y)
def add(self, x1, y1, x2, y2):
return self._add(self._cord_slope(x1, y1, x2, y2), x1, y1, x2, y2)
def double(self, x, y):
return self._add(self._tangent_slope(x, y), x, y, x, y)
def scalar_multiply(point, n):
pass
#def yfromx(self, x, is_top = True):
# r = np.sqrt((x**3) + (self.a * x**2) + self.b)
# r = +r if is_top else -r
# return r
class EllipticCurveOverFiniteField(Object):
def __init__(self, a, b, mod):
self.a = a
self.b = b
self.mod = mod
self._points()
def _points(self):
self.xs = []
self.ys = []
def iterih_square(x):
return ((x**3) + (self.a * x**2) + self.b) % self.mod
for x in range(0, self.mod):
if libnum.has_sqrtmod_prime_power(iterih_square(x), self.mod, 1):
square_roots = libnum.sqrtmod_prime_power(iterih_square(x), self.mod, 1)
for sr in square_roots:
self.ys.append(sr)
self.xs.append(x)
def points(self):
return self.xs, self.ys
def add(self, x1, y1, x2, y2):
s = line_slope(x1, y1, x2, y2)
x = (s**2 - x1 - x2) % self.mod
y = (s * (x1 - x) - y1) % self.mod
return (x, y)
def double(self, x, y):
return 0, 0
def scalar_multiply(point, n):
pass
def elliptic_curve_factory(is_finite, a, b, mod, curve = None):
if curve != None:
a = curve.a
b = curve.b
try:
mod = curve.mod
except:
mod = mod
if is_finite:
return EllipticCurveOverFiniteField(a, b, mod)
else:
return EllipticCurve(a, b)