Files
Geroi-Kodeksa/RSA-Crypto/solve.sage
2026-03-02 21:44:22 +03:00

64 lines
1.4 KiB
Python

#!/usr/bin/env sage
# -*- coding: utf-8 -*-
import re
import sys
def parse_task(path):
text = open(path, "r", encoding="utf-8").read()
def pick(name):
m = re.search(rf"^{name}\s*=\s*([0-9]+)\s*$", text, re.MULTILINE)
if not m:
raise RuntimeError(f"cannot find {name} in {path}")
return Integer(m.group(1))
N = pick("N")
e = pick("e")
c = pick("c")
p_revealed = pick("p_revealed")
return N, e, c, p_revealed
def main():
task_path = sys.argv[1] if len(sys.argv) > 1 else "public/task.txt"
N, e, c, p_revealed = parse_task(task_path)
# From src/chal.py
hidden_bits = 448
X = 2 ** hidden_bits
print(f"[*] N bits: {N.nbits()}")
print(f"[*] hidden bits: {hidden_bits}")
print("[*] running Coppersmith small_roots...")
R = Zmod(N)
P.<x> = PolynomialRing(R)
f = x + p_revealed
roots = f.small_roots(X=X, beta=0.4)
if not roots:
raise RuntimeError("small_roots found no solution")
x0 = Integer(roots[0])
p = Integer(p_revealed + x0)
if N % p != 0:
raise RuntimeError("candidate p does not divide N")
q = Integer(N // p)
phi = (p - 1) * (q - 1)
d = Integer(inverse_mod(e, phi))
m = Integer(power_mod(c, d, N))
m_int = int(m)
flag = m_int.to_bytes((m_int.bit_length() + 7) // 8, "big")
try:
print(flag.decode("utf-8"))
except Exception:
print(flag)
if __name__ == "__main__":
main()