304 words
2 minutes
RSA 101

Overview#

You’re given RSA parameters and a ciphertext. Factoring n via FactorDB yields a very small prime p = 101 and a large prime q. Standard RSA decryption m = c^d mod n returns a number that doesn’t decode to ASCII.

The twist: the original message M was larger than the modulus n, so encryption implicitly reduced it modulo n. After decryption, you get M mod n; to recover M, you add back (a multiple of) n.

Given Parameters#

  • p = 101
  • q = 313846144900241708687128313929756784551
  • n = 31698460634924412577399959706905435239651
  • e = 65537
  • c = 23648999580642514140599125257944114844209

Math#

  • phi(n) = (p - 1)(q - 1)
  • d = e^-1 mod phi(n)
  • m_dec = c^d mod n
  • If original M >= n, encryption sent M mod n. After decryption we get m_dec = M mod n.
  • Recover M by testing M = m_dec + k*n for small k >= 0 until bytes decode. Here k = 1 works.

Solution Script#

import sympy as sp
p = 101
q = 313846144900241708687128313929756784551
n = 31698460634924412577399959706905435239651
e = 65537
c = 23648999580642514140599125257944114844209
# Sanity checks
assert p * q == n
assert sp.isprime(p) and sp.isprime(q)
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m_dec = pow(c, d, n)
print("m_dec =", m_dec)
# Try adding multiples of n until it decodes
def try_decode(x: int):
try:
h = hex(x)[2:]
if len(h) % 2:
h = "0" + h
return bytes.fromhex(h).decode()
except Exception:
return None
flag = None
for k in range(0, 5):
candidate = m_dec + k * n
s = try_decode(candidate)
if s and s.startswith("v1t{") and s.endswith("}"):
flag = s
print("k =", k, "->", flag)
break
assert flag is not None

Why This Works#

  • RSA encrypts modulo n. If the original message M is larger than n, the actual encrypted value is based on M mod n.
  • Decryption returns the reduced message. Adding one modulus (or a few) reconstructs a valid preimage that maps to ASCII.

Flag#

v1t{RSA_101_b4by}
RSA 101
https://daryx.vercel.app/posts/v1tctf-2025-rsa-101/
Author
Daryx
Published at
2025-01-10
License
CC BY-NC-SA 4.0