kashiCTF 2026 - Broadcast
We sent the same announcement to three servers for redundancy. Each server has its own RSA key. Intercept all three — maybe you can piece something together.
Initial Analysis
The challenge provides an output.txt containing an
exponent \(e=3\), three moduli (\(n1, n2, n3\)), and three ciphertexts (\(c1, c2, c3\)). By examining the data, we
notice:
- Low Exponent: \(e = 3\) is very small.
- Identical Ciphertexts: \(c1 = c2 = c3\). This means the raw message \(M\) was not padded differently for each server.
- Magnitude of \(c\): The ciphertext \(c\) is significantly smaller than any of the moduli \(n\).
In RSA, the encryption process is \(c = M^e \pmod n\). Usually, \(M^e\) is much larger than \(n\). However, if \(M^e < n\), then the modulo operation has no effect, and \(c = M^e\).
Solution
Since \(c < n_i\) and \(e=3\), the message \(M\) can be recovered simply by calculating the integer cube root of \(c\): \[M = \sqrt[3]{c}\]
Implementation
Using Python and the gmpy2 library, we can solve for
\(M\):
1 | import gmpy2 |
Note: This challenge is a simplified version of Håstad's Broadcast Attack. While Håstad's attack typically uses the Chinese Remainder Theorem (CRT) to solve for \(M^e\) when \(M^e > n_i\), the small size of the message relative to the key size here allowed for a direct cubic root calculation.