""" supercurve.py An implementation of a weak elliptic curve over a prime field in standard Weirstrauss form: y^2 = x^3 + ax + b Derived from: https://github.com/andreacorbellini/ecc/blob/master/logs/common.py """ class SuperCurve: def __init__(self, field, order, a, b, g): """ a, b = coefficients g = base point """ self.field = field self.order = order self.a = a self.b = b self.g = g assert pow(2, field - 1, field) == 1 assert (4 * a * a * a + 27 * b * b) % field != 0 def __str__(self): return "a = {}\nb = {}\np = {}\nn = {}".format(self.a, self.b, self.field, self.order) def is_on_curve(self, point): if point is None: return True (x, y) = point return (y * y - x * x * x - self.a * x - self.b) % self.field == 0 def add(self, p1, p2): assert self.is_on_curve(p1) assert self.is_on_curve(p2) if p1 is None: return p2 if p2 is None: return p1 (x1, y1) = p1 (x2, y2) = p2 if x1 == x2 and y1 != y2: return None if x1 == x2: m = (3 * x1 * x1 + self.a) * SuperCurve.inv_mod(2 * y1, self.field) else: m = (y1 - y2) * SuperCurve.inv_mod(x1 - x2, self.field) x3 = m * m - x1 - x2 y3 = y1 + m * (x3 - x1) result = (x3 % self.field, -y3 % self.field) assert self.is_on_curve(result) return result def double(self, p): return self.add(p, p) def neg(self, p): if p is None: return None (x, y) = p res = x, -y % self.field assert self.is_on_curve(res) return res def mult(self, scal, point): if scal % self.order == 0 or point is None: return None if scal < 0: return self.neg(self.mult(-scal, point)) result = None addend = point while scal: if scal & 1: result = self.add(result, addend) addend = self.double(addend) scal >>= 1 return result @staticmethod def inv_mod(n, p): if n == 0: raise Exception if n < 0: return p - SuperCurve.inv_mod(-n, p) s, old_s = 0, 1 t, old_t = 1, 0 r, old_r = p, n while r != 0: quotient = old_r // r old_r, r = r, old_r - quotient * r old_s, s = s, old_s - quotient * s old_t, t = t, old_s - quotient * t gcd, x, y = old_r, old_s, old_t assert gcd == 1 assert (n * x) % p == 1 return x % p curve = SuperCurve( field = 14753, order = 14660, a = 1, b = -1, g = (1, 1), )
#!/usr/bin/env python3 import random from supercurve import SuperCurve, curve def main(): curve = SuperCurve( field = 14753, order = 7919, a = 1, b = -1, g = (1, 1), ) # print curve parameters generically print(curve) # xP = Q secret_scalar = random.randrange(curve.order) base = curve.g pub = curve.mult(secret_scalar, base) print("Public key: {}".format(pub)) print("Secret scalar: {}".format(secret_scalar)) while True: print("What is the secret?") user_input = input("Asking for secret") user_input = int(user_input) if curve.mult(user_input, base) == pub: with open("flag.txt", "r") as f: print(f.read()) break else: print("WRONGGG!") continue return 0 if __name__ == "__main__": exit(main())
なんかソースコードめっちゃあるけど、EllipticCurveのorderが小さいので雑にdiscrete_logすれば良い
from sage.all import * from ptrlib import * EC = EllipticCurve(GF(14753), [1, -1]) G = EC((1, 1)) sock = Socket("jctf.tk", 12345) sock.recvuntil("ublic key: ") x, y = eval(sock.recvline().decode()) Q = EC((x, y)) s = G.discrete_log(Q) print(s) print(s * G) print(Q) sock.sendline(str(s)) sock.interactive()