ASIS CTF 2020 | Elliptic Curve

EllipticCurve

楕円曲線上に点  (x, y), (x + 1, y), (x + 2, y)が存在することを教えられ、その三点のうち、ある一点  Pを渡されるので、 d * Pを計算して送る

ここでは、 (x, y)を貰ったと仮定する

   y^2 = (x+2)^3 + a(x + 2) + b (mod p)
       = x^3 + 6x^2 + 12x + 8 + ax + 2a + b (mod p)
   y^2 = (x+1)^3 + a(x + 1) + b (mod p)
-)     = x^3 + 3x^2 + 3x + 1 +ax + a + b (mod p)
----------------------------------------------------
   0   = 3x^2 + 9x + 7 + a (mod p)

   y^2 = (x+1)^3 + a(x + 1) + b (mod p)
       = x^3 + 3x^2 + 3x + 1 +ax + a + b (mod p)
-) y^2 = x^3 + ax + b (mod p)
----------------------------------------------------
   0   = 3x^2 + 3x + 1 + a (mod p)

   0   = 3x^2 + 9x + 7 + a (mod p)
-) 0   = 3x^2 + 3x + 1 + a (mod p)
----------------------------------------------------
   0   = 6x + 6 (mod p)

上式より、 6x + 6 = kpが得られる。さらに6で割って x + 1 = kpだが、 p以上のパラメータは存在し得ないので x + 1 = pとしていい(多分)。

あとはASIS CTF Quals 2019 | Halloween Partyを思い出しながら解くだけ

from sage.all import *
from ptrlib import *
import proofofwork


while True:
    sock = Socket("76.74.178.201", 9531)
    shax, h, l= sock.recvregex(r"that ([^ ]+?)\(X\)\[-6:\] = ([0-9a-f]{6}) and len\(X\) = (.+)")
    h = h.decode()
    print(shax, h, l)
    if shax == b'sha1':
        s = proofofwork.sha1('?' * (40 - 6) + h, text=b'?' * int(l))
    elif shax == b'md5':
        s = proofofwork.md5('?' * (32 - 6) + h, text=b'?' * int(l))
    elif shax == b'sha256':
        s = proofofwork.sha256('?' * (64 - 6) + h, text=b'?' * int(l))
    else:
        sock.close()
        continue
    break
sock.sendline(s)

x, y = [int(x) for x in sock.recvregex(r"P = \(([0-9]+), ([0-9]+)\)")]
s = int(sock.recvregex(r"Send the ([0-9]+) \* P")[0])

origx = x
print("x = {}, y = {}, s = {}".format(x, y, s))
# find p
if is_prime(x + 1):
    p = x + 1
elif is_prime(x):
    p = x
    x = x - 1
elif is_prime(x - 1):
    p = x - 1
    x = x - 2
else:
    assert False

# find a
_, a = PolynomialRing(GF(p), "a").objgen()
f = 3 * x**2 + 3*x + 1 + a
a = int(f.roots()[0][0])

# find b
_, b = PolynomialRing(GF(p), "b").objgen()
f = x**3 + a*x + b - y**2
b = int(f.roots()[0][0])


EC = EllipticCurve(GF(p), [a, b])
print("p = {}, a = {}, b = {}".format(p, a, b))

# check
P = EC((x, y))
P = EC((x+1, y))
P = EC((x+2, y))

P = EC((origx, y))
Q = (s * P).xy()

sock.sendline("({}, {})".format(*Q))
sock.interactive()