#!/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. = 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()