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()
if len(roots) == 1:
alpha = roots[0][0]
u = (Gx - alpha) / Gy
v = (Px - alpha) / Py
return int(v / u)
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)}.")