stuff
This commit is contained in:
parent
4f80bf0d5c
commit
e53fe3436e
@ -1,6 +1,7 @@
|
||||
from util import Object
|
||||
|
||||
import numpy as np
|
||||
# XXX: remove this
|
||||
import libnum
|
||||
|
||||
CURVE_LINSPACE_OFFSET = 10
|
||||
@ -14,50 +15,63 @@ DEFAULT_CURVES = {
|
||||
'secp256k1 (BTC)': (0, 7, 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1),
|
||||
}
|
||||
|
||||
# XXX
|
||||
def init_arg_getter_righer(f, *args):
|
||||
def g(*args):
|
||||
return f(args[0], args[1], args[2])
|
||||
return g
|
||||
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):
|
||||
@init_arg_getter_righer
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
self._points()
|
||||
def _points(self):
|
||||
def iterih_squre(x):
|
||||
def iterih_square(x):
|
||||
return (x**3) + (self.a * x**2) + self.b
|
||||
start = -1
|
||||
for start in np.linspace(-10, 0, 2000):
|
||||
if iterih_squre(start) > 0:
|
||||
break
|
||||
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_squre(xi))
|
||||
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 add(self, p1, p2):
|
||||
p1x, p1y = p1
|
||||
p2x, p2y = p2
|
||||
s = (p2y - p1y) / (p2x - p1x)
|
||||
x = s**2 - p1x - p2x
|
||||
y = s * (p1x - x) - p1y
|
||||
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
|
||||
#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
|
||||
|
||||
def EllipticCurveOverFiniteField(Object):
|
||||
class EllipticCurveOverFiniteField(Object):
|
||||
def __init__(self, a, b, mod):
|
||||
self.a = a
|
||||
self.b = b
|
||||
@ -66,13 +80,36 @@ def EllipticCurveOverFiniteField(Object):
|
||||
def _points(self):
|
||||
self.xs = []
|
||||
self.ys = []
|
||||
def y_squared(x):
|
||||
return (x**a + b) % mod
|
||||
for x in range(0, mod):
|
||||
if libnum.has_sqrtmod_prime_power(y_squared(x), mod, 1):
|
||||
square_roots = libnum.sqrtmod_prime_power(y_squared(x), mod, 1)
|
||||
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)
|
||||
|
||||
|
@ -2,20 +2,51 @@ from elliptic_curve import *
|
||||
|
||||
plots = []
|
||||
|
||||
def is_too_far_away(x, y):
|
||||
return x > 100 or x < -100 or y > 100 or y < -100
|
||||
|
||||
#state.update_points(state.curve.xs[0])
|
||||
#state.update_points(state.curve.xs[1], False)
|
||||
|
||||
# XXX this was used for testing displaying points on the curve
|
||||
def update_points(x, is_top = True):
|
||||
y = state.curve.yfromx(x, is_top)
|
||||
if y == y: # False if NaN
|
||||
state.points.append((x, y))
|
||||
|
||||
def addition(ax, curve, x1, y1, x2, y2):
|
||||
def display_elliptic_curve(ax, curve):
|
||||
global plots
|
||||
p = curve.add((x1, y1), (x2, y2))
|
||||
print((x1, y1), (x2, y2), p)
|
||||
plots += ax.plot(*curve.points(), color='red')
|
||||
|
||||
def display_elliptic_curve_over_finite_field(ax, curve):
|
||||
global plots
|
||||
xs, ys = curve.points()
|
||||
plots += [ax.scatter(
|
||||
xs,
|
||||
ys,
|
||||
color='red', s=20, marker='o'
|
||||
)]
|
||||
|
||||
def double_elliptic_curve(ax, curve, x, y):
|
||||
global plots
|
||||
p = curve.double(x, y)
|
||||
plots += ax.plot([x], [y], 'o')
|
||||
plots += [ax.axline(
|
||||
(x, y),
|
||||
(p[0], -p[1]),
|
||||
linestyle='--'
|
||||
)]
|
||||
if not is_too_far_away(*p):
|
||||
plots += [ax.axline(
|
||||
p,
|
||||
(p[0], p[1] + 1),
|
||||
linestyle='--'
|
||||
)]
|
||||
plots += ax.plot([p[0]], [p[1]], 'o')
|
||||
|
||||
def double_elliptic_curve_over_finite_field(ax, curve, x, y):
|
||||
pass
|
||||
|
||||
def clear():
|
||||
global plots
|
||||
for i in plots:
|
||||
i.remove()
|
||||
plots = []
|
||||
|
||||
def addition_elliptic_curve(ax, curve, x1, y1, x2, y2):
|
||||
global plots
|
||||
p = curve.add(x1, y1, x2, y2)
|
||||
plots += [ax.axline(
|
||||
(x1, y1),
|
||||
(x2, y2),
|
||||
@ -23,7 +54,7 @@ def addition(ax, curve, x1, y1, x2, y2):
|
||||
)]
|
||||
xa = [x1, x2]
|
||||
ya = [y1, y2]
|
||||
if p[0] < 100 and p[0] > -100 and p[1] < 100 and p[1] > -100:
|
||||
if not is_too_far_away(*p):
|
||||
xa.append(p[0])
|
||||
ya.append(p[1])
|
||||
plots += [ax.axline(
|
||||
@ -33,23 +64,30 @@ def addition(ax, curve, x1, y1, x2, y2):
|
||||
)]
|
||||
plots += ax.plot(xa, ya, 'o')
|
||||
|
||||
def clear():
|
||||
def addition_elliptic_curve_over_finite_field(ax, curve, x1, y1, x2, y2):
|
||||
global plots
|
||||
for i in plots:
|
||||
i.remove()
|
||||
plots = []
|
||||
|
||||
def display_elliptic_curve(ax, curve):
|
||||
global plots
|
||||
plots += ax.plot(*curve.points(), color='red')
|
||||
|
||||
def display_elliptic_curve_over_finite_field(ax_curve):
|
||||
xs, xy = curve.points()
|
||||
plots += [ax.scatter(
|
||||
[i[0] for i in xs],
|
||||
[i[1] for i in xy],
|
||||
color='red', s=20, marker='o'
|
||||
p = curve.add(x1, y1, x2, y2)
|
||||
x_axis_intersection = intersection(x1, y1, x2, y2, 0, 0, 1, 0)
|
||||
limit_intersection = intersection(x1, y1, x2, y2, 0, curve.mod-1, 1, curve.mod-1)
|
||||
print(x_axis_intersection, limit_intersection)
|
||||
plots += [ax.plot(
|
||||
(x_axis_intersection[0], limit_intersection[0]),
|
||||
(x_axis_intersection[1], limit_intersection[1]),
|
||||
linestyle='--'
|
||||
)]
|
||||
plots += ax.plot([p[0], p[1]], 'x')
|
||||
|
||||
def addition(ax, curve, x1, y1, x2, y2):
|
||||
if isinstance(curve, EllipticCurve):
|
||||
addition_elliptic_curve(ax, curve, x1, y1, x2, y2)
|
||||
elif isinstance(curve, EllipticCurveOverFiniteField):
|
||||
addition_elliptic_curve_over_finite_field(ax, curve, x1, y1, x2, y2)
|
||||
|
||||
def double(ax, curve, x, y):
|
||||
if isinstance(curve, EllipticCurve):
|
||||
double_elliptic_curve(ax, curve, x, y)
|
||||
elif isinstance(curve, EllipticCurveOverFiniteField):
|
||||
double_elliptic_curve_over_finite_field(ax, curve, x, y)
|
||||
|
||||
def display(ax, curve):
|
||||
if isinstance(curve, EllipticCurve):
|
||||
|
37
gui.py
37
gui.py
@ -16,20 +16,21 @@ def display():
|
||||
elliptic_curve_display.display(state.ax, state.curve)
|
||||
ps = state.curve.points()
|
||||
elliptic_curve_display.addition(state.ax, state.curve, ps[0][3], ps[1][3], ps[0][6], ps[1][6])
|
||||
elliptic_curve_display.double(state.ax, state.curve, ps[0][6], ps[1][6])
|
||||
state.canvas.draw()
|
||||
|
||||
def update_curve(curve=None):
|
||||
global state
|
||||
if curve != None:
|
||||
a, b, mod = curve
|
||||
else:
|
||||
a = int(state.a_input.get())
|
||||
b = int(state.b_input.get())
|
||||
mod = int(state.mod_input.get())
|
||||
state.a_strvar.set(a)
|
||||
state.b_strvar.set(b)
|
||||
state.mod_strvar.set(mod)
|
||||
state.curve = EllipticCurve(a, b, mod)
|
||||
a = int(state.a_input.get())
|
||||
b = int(state.b_input.get())
|
||||
mod = int(state.mod_input.get())
|
||||
state.curve = elliptic_curve_factory(state.is_finite, a, b, mod, curve)
|
||||
state.a_strvar.set(state.curve.a)
|
||||
state.b_strvar.set(state.curve.b)
|
||||
try:
|
||||
state.b_strvar.set(state.curve.mod)
|
||||
except:
|
||||
pass
|
||||
|
||||
def rerender(curve=None):
|
||||
if curve != None:
|
||||
@ -44,7 +45,7 @@ def init(curve):
|
||||
state.points = list()
|
||||
|
||||
tk_init()
|
||||
update_curve(DEFAULT_CURVES['Default'])
|
||||
state.curve = elliptic_curve_factory(state.is_finite, *DEFAULT_CURVES['Default'])
|
||||
tk_fill()
|
||||
|
||||
def tk_init():
|
||||
@ -57,12 +58,17 @@ def tk_init():
|
||||
state.controls = ttk.Frame(root)
|
||||
state.toolbar = NavigationToolbar2Tk(state.canvas, root, pack_toolbar=False)
|
||||
state.toolbar.update()
|
||||
state.a_strvar = tk.StringVar()
|
||||
state.b_strvar = tk.StringVar()
|
||||
state.mod_strvar = tk.StringVar()
|
||||
state.a_strvar = tk.StringVar(value=str(0))
|
||||
state.b_strvar = tk.StringVar(value=str(0))
|
||||
state.mod_strvar = tk.StringVar(value=str(0))
|
||||
state.is_finite = tk.IntVar(value=0)
|
||||
|
||||
def tk_fill():
|
||||
global state
|
||||
# Finite field view toggle
|
||||
tk.Checkbutton(state.controls, text="Finite field view",
|
||||
variable=state.is_finite, command=lambda: rerender(state.curve),
|
||||
).pack()
|
||||
# Equation -- y^2 = x^3 + a * x^2 + b
|
||||
state.curve_equation = ttk.Frame(state.controls)
|
||||
equation = [
|
||||
@ -85,8 +91,7 @@ def tk_fill():
|
||||
("b", "red", state.b_strvar.get(), "b_input"),
|
||||
("modulos", "magenta", state.mod_strvar.get(), "mod_input"),
|
||||
]
|
||||
f = ttk.Frame(state.controls)
|
||||
f.pack()
|
||||
(f := ttk.Frame(state.controls)).pack()
|
||||
for i, d in enumerate([{k:v for k,v in zip(entry_keys, t)} for t in entry_values]):
|
||||
ttk.Label(f, text=d["name"], foreground=d["color"]).grid(row=i, column=0)
|
||||
w = state[d["label_name"]] = tk.Scale(f, from_=0, to=100, orient=tk.HORIZONTAL, length=200)
|
||||
|
Loading…
x
Reference in New Issue
Block a user