-
Notifications
You must be signed in to change notification settings - Fork 121
/
singular_curve.py
44 lines (38 loc) · 1.4 KB
/
singular_curve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from sage.all import GF
def attack(p, a2, a4, a6, Gx, Gy, Px, Py):
"""
Solves the discrete logarithm problem on a singular curve (y^2 = x^3 + a2 * x^2 + a4 * x + a6).
:param p: the prime of the curve base ring
:param a2: the a2 parameter of the curve
:param a4: the a4 parameter of the curve
:param a6: the a6 parameter of the curve
:param Gx: the base point x value
:param Gy: the base point y value
:param Px: the point multiplication result x value
:param Py: the point multiplication result y value
:return: l such that l * G == P
"""
x = GF(p)["x"].gen()
f = x ** 3 + a2 * x ** 2 + a4 * x + a6
roots = f.roots()
# Singular point is a cusp.
if len(roots) == 1:
alpha = roots[0][0]
u = (Gx - alpha) / Gy
v = (Px - alpha) / Py
return int(v / u)
# Singular point is a node.
if len(roots) == 2:
if roots[0][1] == 2:
alpha = roots[0][0]
beta = roots[1][0]
elif roots[1][1] == 2:
alpha = roots[1][0]
beta = roots[0][0]
else:
raise ValueError("Expected root with multiplicity 2.")
t = (alpha - beta).sqrt()
u = (Gy + t * (Gx - alpha)) / (Gy - t * (Gx - alpha))
v = (Py + t * (Px - alpha)) / (Py - t * (Px - alpha))
return int(v.log(u))
raise ValueError(f"Unexpected number of roots {len(roots)}.")