RSA Attack Toolkit
A systematic approach to breaking RSA encryption in CTFs and crypto challenges.
Quick Triage Checklist
When you encounter an RSA challenge, collect these values first:
- Core parameters:
n(modulus),e(public exponent),c(ciphertext) - Multiple ciphertexts: Are there several
cvalues? Same or different moduli? - Message relationships: Same plaintext encrypted differently? Structured plaintext?
- Leaks: Partial
p/q, bits ofd,dp/dq, known padding patterns
Then systematically try attacks in this order:
- Factorization check - Try
factordb.comorsage: factor(n)for small moduli - Low exponent patterns - Check if
e=3or other small values, look for broadcast - Common modulus / shared primes - Check GCDs between moduli
- Lattice methods - Use Coppersmith/LLL when partial information exists
Attack Patterns
Common Modulus Attack
When to use: Two ciphertexts encrypt the same message under the same modulus n but with different exponents e1, e2 where gcd(e1, e2) = 1.
How it works: Use the extended Euclidean algorithm to recover m:
m = c1^a * c2^b mod n
where a*e1 + b*e2 = 1.
Steps:
- Compute
(a, b) = extended_gcd(e1, e2)so thata*e1 + b*e2 = 1 - If
a < 0, computeinv(c1)^(-a) mod n(modular inverse) - If
b < 0, computeinv(c2)^(-b) mod n - Multiply results and reduce modulo
n
Script: Use scripts/common_modulus_attack.py
Shared Primes Across Moduli
When to use: Multiple RSA moduli from the same challenge, especially when the problem mentions "many keys generated quickly" or "bad randomness".
How it works: If gcd(n1, n2) != 1, the moduli share a prime factor - catastrophic key generation failure.
Steps:
- For each pair of moduli, compute
g = gcd(n1, n2) - If
g > 1, you found a shared primep = g - Compute
q = n // pto factor the modulus - Use
p, qto compute private key and decrypt
Script: Use scripts/shared_prime_check.py
Håstad Broadcast Attack
When to use: Same plaintext sent to multiple recipients with small e (often e=3) and no proper padding.
Technical condition: You need e ciphertexts of the same message under pairwise-coprime moduli n_i.
How it works:
- Use Chinese Remainder Theorem (CRT) to recover
M = m^eover the productN = Π n_i - If
m^e < N, thenMis the true integer power - Compute
m = integer_root(M, e)
Script: Use scripts/hadast_broadcast.py
Wiener Attack (Small Private Exponent)
When to use: When d is too small (typically d < n^0.25 / 3).
How it works: Continued fractions of e/n can recover d when it's small enough.
Steps:
- Compute continued fraction expansion of
e/n - For each convergent
k/d, check if it yields valid RSA parameters - If valid, use
dto decrypt
Script: Use scripts/wiener_attack.py
Related-Message Attacks
When to use: Two ciphertexts under the same modulus with algebraically related messages (e.g., m2 = a*m1 + b).
Requirements:
- Same modulus
n - Same exponent
e - Known relationship between plaintexts
How it works: Set up polynomials modulo n and compute GCD to find the message.
Tooling: Use SageMath with polynomial GCD computation.
Lattice Methods (Coppersmith/LLL)
When to use: You have partial information that makes the unknown "small".
Typical hints:
- "We leaked the top/bottom bits of p"
- "The flag is embedded like:
m = bytes_to_long(b"HTB{" + unknown + b"}")" - "We used RSA but with a small random padding"
What it handles:
- Partially known plaintext (structured message with unknown tail)
- Partially known
p/q(high or low bits leaked) - Small unknown differences between related values
Tooling: Use SageMath with Coppersmith templates.
Resources:
- Sage CTF crypto templates: https://github.com/defund/coppersmith
- Survey reference: https://martinralbrecht.wordpress.com/2013/05/06/coppersmiths-method/
Textbook RSA Pitfalls
If you see these patterns, algebraic attacks become much more likely:
- No OAEP/PSS padding, raw modular exponentiation
- Deterministic encryption (same plaintext → same ciphertext)
- Small public exponents without proper padding
Tools
- RsaCtfTool: https://github.com/Ganapati/RsaCtfTool - Automated RSA attack tool
- SageMath: https://www.sagemath.org/ - For CRT, roots, continued fractions, lattice methods
Workflow
- Parse the challenge - Extract all
n,e,cvalues and note relationships - Run triage - Check factorization, look for obvious patterns
- Match to attack - Identify which attack pattern fits
- Execute - Use the appropriate script or Sage template
- Verify - Check if the decrypted message makes sense (look for flag patterns)
Example Challenge Patterns
Pattern 1 - Common Modulus:
"Here are two ciphertexts of the same message with different exponents"
n = 0x...
e1 = 65537, c1 = 0x...
e2 = 3, c2 = 0x...
→ Use common modulus attack
Pattern 2 - Shared Primes:
"We generated 100 RSA keys quickly"
n1 = 0x..., n2 = 0x..., n3 = 0x...
→ Check GCDs between all pairs
Pattern 3 - Broadcast:
"Same message sent to 3 recipients with e=3"
n1, c1 = ...
n2, c2 = ...
n3, c3 = ...
→ Use Håstad broadcast attack
Pattern 4 - Partial Key:
"We leaked the top 50 bits of p"
n = 0x...
p_high = 0x...
→ Use Coppersmith with partial key recovery