Generating primes is expensive. I optimized my key generation to be
twice as fast. The modulus is 4096 bits — perfectly secure.
Initial Analysis
The hint "optimized my key generation to be twice as fast" suggests
that instead of generating two distinct large primes, the author might
have reused the same prime (\(n =
p^2\)) or chosen two primes that are extremely close to each
other. This makes the modulus vulnerable to Fermat's Factorization
Method or simply taking the square root.
Extraction & Decoding
Given a 4096-bit modulus \(n\), we
can check if it's a perfect square or if its factors are close to \(\sqrt{n}\) by starting from \(\lfloor\sqrt{n}\rfloor\) and searching
downwards. Once factored, we calculate \(\phi(n)\), derive the private key \(d\), and decrypt the AES key which was used
to encrypt the flag.
import math import base64 from Crypto.Util.number import long_to_bytes, bytes_to_long from Crypto.Util.Padding import unpad from Crypto.Cipher import AES
# Modulus and public exponent n = 0x752a94a112ba0ce096f47934dac094d3d07b8c036613938142c0d4c15fc82692eee38d2457dd8d16472c4ddbe8cb5e2a6331e0ca0351094fc9516559768ebfe44509154d64116fa1fe1daf698413d37c9fe3406555f3190e29d99bee0cdd663d531c8e818f2686c7ad24338b4e93c6bfbd1b5a6dc5161316b2cb9ac1ae05a4ac43fdeb3b024b2e00dfcd87069ea1645996d9ad16ac3a9697414c17279112303a1d21136a99dc47628e15a3d6e18779de7aec310331dff1a81871b03e214de09f56c0f3de02f9f399be4ebc094f34b578d311a8b48e9c6cf2fa2f4e321f1dab0a99e5b9d99464c19452d9cc21544ac8e32fb9f13d1b2990758de0876de465cbd3632f846ef49fd7b97abee2ce529cfbc75a0d0792df6cc8091198134e9f646cf7d33c85c4ddd2c4b9a248c2c470d7369ebc7245bcec049455da2ceb742b26058514418398149d03cd1ad74a997375d0462a43e73aa62fc1f7e0dcc67e8f1559073074b9b8d3c37edfcfce67fd1822227933c5a14425d76119fc0a25da4c059761c86bc3077c4d096d9b9f6ae2faf728dbf24d48fa74d99c8c0d8780d2963ca9eccef0dd847ce22fc5b13793981257a9d4dd1af965e9baa5bd9fc4e3321cf8c6fd9871e342e5ae0dff19ab6e9fd8e14b5cc766b92df3306ef63af248b019528928644007c17e31918f9fdf10daeadc1eb8abeb6297bdc8f8e9b27c591f12159479 e = 65537
# Factor n p = math.isqrt(n) while n % p != 0: p -= 1 q = n // p
# Calculate phi if p == q: phi = p * (p - 1) else: phi = (p - 1) * (q - 1)
# Decrypt Flag iv = base64.b64decode("XSCnpZLyN1Oin7F67hOKWQ==") flag_ct = base64.b64decode("n+H1n3ezKEm0ulyLMcp/ShxLZAddKX7y848o/Lf/56qDev/DPBz+IRcJ14yHWGOuodMaMwyLZi9er7slNa+QMw==")
cipher = AES.new(aes_key, AES.MODE_CBC, iv) flag = unpad(bytes(cipher.decrypt(flag_ct)), AES.block_size).decode()