From 5659065516478bb0384889dc0c4be293470c34cc Mon Sep 17 00:00:00 2001 From: Maxime Vorwerk Date: Wed, 31 Jul 2024 01:20:37 +0200 Subject: [PATCH] Very Smooth --- very_smooth/gen.py | 89 ++++++++++++++++++++++++++++++++++++++++++ very_smooth/output.txt | 2 + very_smooth/sol.py | 65 ++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100755 very_smooth/gen.py create mode 100755 very_smooth/output.txt create mode 100755 very_smooth/sol.py diff --git a/very_smooth/gen.py b/very_smooth/gen.py new file mode 100755 index 0000000..83cb476 --- /dev/null +++ b/very_smooth/gen.py @@ -0,0 +1,89 @@ +#!python3 + +from binascii import hexlify +from gmpy2 import * +import math +import os +import sys + +if sys.version_info < (3, 9): + math.gcd = gcd + math.lcm = lcm + +_DEBUG = False + +FLAG = open('flag.txt').read().strip() +FLAG = mpz(hexlify(FLAG.encode()), 16) +SEED = mpz(hexlify(os.urandom(32)).decode(), 16) +STATE = random_state(SEED) + +def get_prime(state, bits): + return next_prime(mpz_urandomb(state, bits) | (1 << (bits - 1))) + +def get_smooth_prime(state, bits, smoothness=16): + p = mpz(2) + p_factors = [p] + while p.bit_length() < bits - 2 * smoothness: + factor = get_prime(state, smoothness) + p_factors.append(factor) + p *= factor + + bitcnt = (bits - p.bit_length()) // 2 + + while True: + prime1 = get_prime(state, bitcnt) + prime2 = get_prime(state, bitcnt) + tmpp = p * prime1 * prime2 + if tmpp.bit_length() < bits: + bitcnt += 1 + continue + if tmpp.bit_length() > bits: + bitcnt -= 1 + continue + if is_prime(tmpp + 1): + p_factors.append(prime1) + p_factors.append(prime2) + p = tmpp + 1 + break + + p_factors.sort() + + return (p, p_factors) + +e = 0x10001 + +while True: + p, p_factors = get_smooth_prime(STATE, 1024, 16) + if len(p_factors) != len(set(p_factors)): + continue + # Smoothness should be different or some might encounter issues. + q, q_factors = get_smooth_prime(STATE, 1024, 17) + if len(q_factors) != len(set(q_factors)): + continue + factors = p_factors + q_factors + if e not in factors: + break + +if _DEBUG: + import sys + sys.stderr.write(f'p = {p.digits(16)}\n\n') + sys.stderr.write(f'p_factors = [\n') + for factor in p_factors: + sys.stderr.write(f' {factor.digits(16)},\n') + sys.stderr.write(f']\n\n') + + sys.stderr.write(f'q = {q.digits(16)}\n\n') + sys.stderr.write(f'q_factors = [\n') + for factor in q_factors: + sys.stderr.write(f' {factor.digits(16)},\n') + sys.stderr.write(f']\n\n') + +n = p * q + +m = math.lcm(p - 1, q - 1) +d = pow(e, -1, m) + +c = pow(FLAG, e, n) + +print(f'n = {n.digits(16)}') +print(f'c = {c.digits(16)}') diff --git a/very_smooth/output.txt b/very_smooth/output.txt new file mode 100755 index 0000000..37a8ec7 --- /dev/null +++ b/very_smooth/output.txt @@ -0,0 +1,2 @@ +n = b03ea698ce2b51fb00e11e6fbaf1e5373dc5b0c70eb2b14a36d21e8667be8774eee51f6050a10237f6b24f21204fc8013681e7ed72ed051188f3274aae8f1de0d39389b514c196fa82c98a270bfabefd044da8c687b0e114ebbde82536c0709ac5ad81bfe0077e9d9b798ad5abecee52767e68f8060c45936521fd93893102eb1676f2ff41324a7a6b3dff2e830538e06d25934e9f14bf6b40ab5674fe648e314bf06f84282f5ef52bc1401de3a42eb66e64bcdadd2674348e5bdb7016feda44d719af387a948ad81cbaed10213dd930fc7bc7677d8c4cdab0645d0ff15e6ad6ca37135942c3be08f23e7be0992c8b3370dcdc31045e086d823107fb2e443dc9 +c = a913a96e215b5aa79c702d27fa375c73d06787639c4131fb32877cafefaa8faf70e15f6a17ef2a9a6f5310b157cb287b740e77cb5385081d1853a9104bc16357b259fa2d146bd87398d4ef6f1c078289812952c67792cf9cd745049aeb9d4ab4dff2825a9c0b3381f19b2a67164f9d4de33c25f98bc2f224feb5507b531e1a1c7be5ed2d8ddd01f3fae37245e8cf99c75a21848993d445e1d6d69d555a3e6cc8055704fdde88df9084bda3ea65a9384fa64bf8df4d88946449526320c15d4d2d871638070489adf3f8c95caffeab40b0d137a9319be20cdf6ebbaf037f62093d9bd33edd4ffd7e1929b9ab06252956fd85250a0515ef2b4e035017be5702cdd3 diff --git a/very_smooth/sol.py b/very_smooth/sol.py new file mode 100755 index 0000000..9007bb7 --- /dev/null +++ b/very_smooth/sol.py @@ -0,0 +1,65 @@ +#!python3 +from sage.all import * +from pwn import * + +with open("output.txt", 'r') as f: + lines = f.readlines() + N = Integer(lines[0][4:].strip(), 16) + c = Integer(lines[1][4:].strip(), 16) +log.info(f"N: {N}") +log.info(f"c: {c}") + +e = Integer(0x10001) +log.info(f"e: {e}") + +smooth_bound = 16 +loopmsg = log.progress("calculating p, q") +interval = (0, smooth_bound) +center = 0 +while True: + base = Integer(2) + M = 1 + for p in Primes(): + if p >= smooth_bound: + break + + np = p + while np+p < smooth_bound: + np += p + + M *= np + + g = gcd(pow(base, M, N)-1, N) + + if g == 1 and center == 0: + interval = (smooth_bound, smooth_bound*2) + smooth_bound *= 2 + elif g == 1 and center != 0: + interval = (center, interval[1]) + center = interval[0] + (interval[1] - interval[0])/2 + smooth_bound = center + elif g == N and center == 0: + center = interval[0] + (interval[1] - interval[0])/2 + smooth_bound = center + elif g == N and center != 0: + interval = (interval[0], center) + center = interval[0] + (interval[1] - interval[0])/2 + smooth_bound = center + else: + loopmsg.success("factoring found") + p = int(g) + q = N // p + break + +assert p*q == N +log.info(f"p: {p}") +log.info(f"q: {q}") + +d = pow(e, -1, (p-1)*(q-1)) +log.info(f"d: {d}") + +m = pow(c, d, N) +log.info(f"m: {m}") +m_literal = pack(int(m), 'all', 'big', False) +log.success(f"solution: {m_literal}") +