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
See rsa for a primer
1. Low Public Exponent
For small , the plaintext is trivially recovered by computing the th root of like as .
Link to originalComputing 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! It’s not quite textbook RSA! Therefore this shouldn’t work!
This, however, is a simple padding scheme, so the same principles should apply given is only slightly wider than 1. 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