Skip to content

Commit b860a83

Browse files
author
Release Manager
committed
Trac #34253: Add discrete logarithm for anomalous elliptic curves
A fast method to solve the discrete logarithm in anomalous elliptic curves uses the p-adic logarithm as described in: https://link.springer.com/article/10.1007/s001459900052. I implemented the algorithm based on https://crypto.stackexchange.com/questions/70454 /why-smarts-attack-doesnt-work-on-this-ecdlp/70508#70508 for `EllipticCurvePoint_finite_field` URL: https://trac.sagemath.org/34253 Reported by: gh-sylvainpelissier Ticket author(s): Sylvain Pelissier Reviewer(s): Lorenz Panny
2 parents 02b31cc + 86ad465 commit b860a83

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5311,6 +5311,10 @@ REFERENCES:
53115311
.. [Sma1998] \N.P. Smart, *The algorithmic resolution of Diophantine equations*,
53125312
Number 41 in Student Texts. London Mathematical Society, 1998.
53135313
5314+
.. [Sma1999] \N.P. Smart, *The Discrete Logarithm Problem on Elliptic Curves of Trace One*,
5315+
Journal of Cryptology. 12. 193-196. 1999.
5316+
:doi:`10.1007/s001459900052`.
5317+
53145318
.. [SP2010] Fernando Solano and Michal Pioro, *Lightpath Reconfiguration in WDM
53155319
networks*, IEEE/OSA Journal of Optical Communication and Networking
53165320
2(12):1010-1021, 2010. :doi:`10.1364/JOCN.2.001010`.

src/sage/schemes/elliptic_curves/ell_point.py

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3543,6 +3543,9 @@ def discrete_log(self, Q, ord=None):
35433543
- Otherwise (if this test is inconclusive), check that the Weil
35443544
pairing of `P` and `Q` is trivial.
35453545
3546+
For anomalous curves with `\#E = p`, the
3547+
:meth:`padic_elliptic_logarithm` function is called.
3548+
35463549
INPUT:
35473550
35483551
- ``Q`` (point) -- another point on the same curve as ``self``.
@@ -3601,12 +3604,106 @@ def discrete_log(self, Q, ord=None):
36013604
if n*Q:
36023605
raise ValueError('ECDLog problem has no solution (order of Q does not divide order of P)')
36033606
E = self.curve()
3604-
if hasattr(E, '_order') and E._order.gcd(n**2) == n:
3607+
F = E.base_ring()
3608+
p = F.cardinality()
3609+
if F.is_prime_field() and n == p:
3610+
# Anomalous case
3611+
return self.padic_elliptic_logarithm(Q, p)
3612+
elif hasattr(E, '_order') and E._order.gcd(n**2) == n:
36053613
pass # cyclic rational n-torsion -> okay
36063614
elif self.weil_pairing(Q, n) != 1:
36073615
raise ValueError('ECDLog problem has no solution (non-trivial Weil pairing)')
3616+
36083617
return ZZ(pari.elllog(self.curve(), Q, self, n))
36093618

3619+
def padic_elliptic_logarithm(self,Q, p):
3620+
r"""
3621+
Return the discrete logarithm of `Q` to base `P` = ``self``,
3622+
that is, an integer `x` such that `xP = Q` only for anomalous curves.
3623+
3624+
ALGORITHM:
3625+
3626+
Discrete logarithm computed as in [Sma1999]_ with a loop to avoid
3627+
the canonical lift.
3628+
3629+
INPUT:
3630+
3631+
- ``Q`` (point) -- another point on the same curve as ``self``.
3632+
- ``p`` (integer) -- a prime equals the order of the curve.
3633+
3634+
OUTPUT:
3635+
3636+
(integer) -- The discrete logarithm of `Q` with respect to `P`,
3637+
which is an integer `x` with `0\le x<\mathrm{ord}(P)` such that
3638+
`xP=Q`.
3639+
3640+
AUTHORS:
3641+
3642+
- Sylvain Pelissier (2022) based on Samuel Neves code_.
3643+
3644+
.. _code: https://crypto.stackexchange.com/questions/70454/why-smarts-attack-doesnt-work-on-this-ecdlp/70508#70508
3645+
3646+
EXAMPLES::
3647+
3648+
sage: p=235322474717419
3649+
sage: b=8856682
3650+
sage: E = EllipticCurve(GF(p), [0, b])
3651+
sage: P = E(200673830421813, 57025307876612)
3652+
sage: Q = E(40345734829479, 211738132651297)
3653+
sage: x = P.padic_elliptic_logarithm(Q, p)
3654+
sage: x * P == Q
3655+
True
3656+
3657+
TESTS:
3658+
3659+
Some testing::
3660+
3661+
sage: a = 49850651047495986645822557378918223
3662+
sage: b = 21049438014429831351540675253466229
3663+
sage: p = 54283205379427155782089046839411711
3664+
sage: E = EllipticCurve(GF(p),[a, b])
3665+
sage: P = E.random_point()
3666+
sage: Q = randrange(0, p-1) * P
3667+
sage: x = P.padic_elliptic_logarithm(Q, p)
3668+
sage: x*P == Q
3669+
True
3670+
"""
3671+
E = self.curve()
3672+
F = E.base()
3673+
3674+
if Q.is_zero():
3675+
k = 0
3676+
else:
3677+
for k in range(0,p):
3678+
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + k * p for t in E.a_invariants() ])
3679+
3680+
P_Qps = Eqp.lift_x(ZZ(self.xy()[0]), all=True)
3681+
for P_Qp in P_Qps:
3682+
if F(P_Qp.xy()[1]) == self.xy()[1]:
3683+
break
3684+
3685+
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
3686+
for Q_Qp in Q_Qps:
3687+
if F(Q_Qp.xy()[1]) == Q.xy()[1]:
3688+
break
3689+
3690+
pP = p * P_Qp
3691+
pQ = p * Q_Qp
3692+
if (pP.is_zero() or pQ.is_zero()):
3693+
# Should happen with probability 1/p
3694+
continue
3695+
else:
3696+
break
3697+
3698+
x_P,y_P = pP.xy()
3699+
x_Q,y_Q = pQ.xy()
3700+
3701+
phi_P = -(x_P / y_P)
3702+
phi_Q = -(x_Q / y_Q)
3703+
k = phi_Q / phi_P
3704+
3705+
return ZZ(k % p)
3706+
36103707
def has_finite_order(self):
36113708
r"""
36123709
Return ``True`` if this point has finite additive order as an element

0 commit comments

Comments
 (0)