After noticing this challenge was about elliptic curves, I could not resist having a try at it. The “description” consisted of the following data:
p = 16857450949524777441941817393974784044780411511252189319
A = 16857450949524777441941817393974784044780411507861094535
B = 77986137112576
E: y^2 = x^3 + Ax + B over GF(p)
P = (5732560139258194764535999929325388041568732716579308775, 14532336890195013837874850588152996214121327870156054248)
Q = (2609506039090139098835068603396546214836589143940493046, 8637771092812212464887027788957801177574860926032421582)
Q = secret * P
flag = secret
Hence the task is simply to compute the (discrete) logarithm of Q
with base
P
on an elliptic curve E
given by a Weierstraß equation
This problem is generally infeasible in reasonable time for curves over prime
fields as large as sage
confirms this assumption:
sage: p = 16857450949524777441941817393974784044780411511252189319
sage: A = 16857450949524777441941817393974784044780411507861094535
sage: B = 77986137112576
sage: E = EllipticCurve(GF(p), [0, 0, 0, A, B])
sage: E
Elliptic Curve defined by y^2 = x^3 + 16857450949524777441941817393974784044780411507861094535*x + 77986137112576 over Finite Field of size 16857450949524777441941817393974784044780411511252189319
sage: E.order()
16857450949524777441941817393974784044780411511252189319
sage: E.order() == p
True
The order of
In short, it says that
sage
has an implementation of square roots for
sage
has an implementation of
the formal group including its formal logarithm. That logarithm is a power
series with coefficients in Finally, here’s an implementation producing the solution:
#!/usr/bin/env sage
p = 16857450949524777441941817393974784044780411511252189319
A = 16857450949524777441941817393974784044780411507861094535
B = 77986137112576
xP = 5732560139258194764535999929325388041568732716579308775
yP = 14532336890195013837874850588152996214121327870156054248
xQ = 2609506039090139098835068603396546214836589143940493046
yQ = 8637771092812212464887027788957801177574860926032421582
E = EllipticCurve(GF(p), [0, 0, 0, A, B])
assert E.order() == p
Qp = Qp(p, 2)
Ep = EllipticCurve(Qp, [0, 0, 0, A, B])
yPp = sqrt(Qp(xP) ** 3 + Qp(A) * Qp(xP) + Qp(B))
Pp = Ep(Qp(xP), (-yPp, yPp)[yPp[0] == yP])
yQp = sqrt(Qp(xQ) ** 3 + Qp(A) * Qp(xQ) + Qp(B))
Qp = Ep(Qp(xQ), (-yQp, yQp)[yQp[0] == yQ])
print('Pp = {}'.format(Pp))
print('Qp = {}'.format(Qp))
print('-' * 40)
lQ = Ep.formal_group().log()(- (p * Qp)[0] // (p * Qp)[1]) / p
print('log(Q) = {}'.format(lQ))
lP = Ep.formal_group().log()(- (p * Pp)[0] // (p * Pp)[1]) / p
print('log(P) = {}'.format(lP))
print('-' * 40)
e = lQ / lP
print('e = {}'.format(e))
assert e[0] * E(xP, yP) == E(xQ, yQ)
print('\n--> FLAG: {:d}\n'.format(e[0]))