Problem
Solution
In my writeup for the 2019 edition of this question, I explained the bare necessities of RSA required to solve that problem. The same background is applicable here:
Background
Note
The following only applies to unpadded (i.e. textbook) RSA
Textbook RSA is defined as follows: where is the modulus, is the public key, and is the message. If , then (i.e. the modulus doesn’t work its magic) and can be recovered by computing the th root of since .
Computing such a value requires high-precision arithmetic since is a massive integer. The Python module
Link to originalgmpy2
is great for such circumstances, providing theiroot
function for computing the th root of an integer without truncation or rounding.
But this plaintext has been padded - didn’t I say the attack only applies to unpadded RSA? This is true for the most part, with the caveat of simple padding schemes (e.g. for slightly wider than 1). Under such a padding scheme, we may enumerate different amounts of padding until we find the correct amount.
Script
from gmpy2 import iroot
with open("ciphertext", "r") as f:
n, e, space, c = f.readlines()
n = int(n[3:])
e = int(e[3:])
c = int(c[16:])
for i in range(4096):
# Pad by a multiple of `n`
padded, is_exact = iroot(c + (i * n), e)
if is_exact and pow(padded, e, n) == c:
print(padded.to_bytes(256, "big").decode("utf-8").strip("\x00").strip())
break