Skip to main content
RSA is the most common asymmetric cipher you’ll encounter in CTF cryptography challenges, and almost every RSA challenge is won the same way: you find a parameter that’s too small, a relationship between values that shouldn’t exist, or a shortcut the challenge author took to make the problem solvable. You never break RSA itself — you break the way it was set up. This walkthrough takes you through the most common attack classes, from a basic factoring check all the way through multi-key attacks, with working Python code for each.

Challenge Setup

A typical RSA challenge gives you some combination of the following:
  • n — the public modulus (product of two primes p and q)
  • e — the public exponent (commonly 65537, but sometimes 3 or another small value)
  • c — the ciphertext (an integer: c = m^e mod n)
  • A .pem public key file
  • Sometimes: multiple (n, e, c) triples or the encryption script
Your goal is to recover m (the plaintext message, usually a flag) by finding the private exponent d or by exploiting a structural weakness that lets you bypass the need for d entirely.
Always start by inspecting the numbers. Print the bit length of n, check whether e is unusually small, and look for any values that appear in more than one set of parameters. These observations take thirty seconds and will immediately rule out most attacks — or confirm the right one.

Attack Workflow

1

Inspect the Parameters

Load the key material and check the basics. A 512-bit or smaller modulus is almost certainly factorable. An exponent of 3 opens the door to cube-root attacks. Identical n values across different ciphertexts suggest a common modulus attack.
2

Try Factoring the Modulus

Before running any sophisticated attack, check whether n is already known to be factored. Submit it to factordb.com — many CTF moduli use pre-generated weak primes that have been catalogued there. If factordb doesn’t have it, try sympy or SageMath for small moduli.
Once you have p and q, computing the flag is straightforward:
3

Choose and Execute an Attack

If the modulus doesn’t factor easily, identify which structural attack applies based on the parameters you have. The tabs below cover each major attack class in detail.
4

Decode the Flag

The recovered plaintext m is an integer. Convert it to bytes and look for your flag format (e.g., CTF{...}).

Attack Types

When e = 3 and the message m is small enough that m^3 < n, the modular reduction never activates — which means c = m^3 exactly, with no modular arithmetic involved. You recover m by taking the integer cube root of c.
If the cube root isn’t exact, m^3 wrapped around n. Try the following: for k in a small range, check whether gmpy2.iroot(c + k * n, 3) is exact. This works when padding is minimal.
This attack only works when no proper padding (like OAEP) is applied. A well-padded RSA ciphertext is not vulnerable to simple cube-root recovery even with e = 3.

Automating with RsaCtfTool

When you’re not sure which attack applies, or you want a quick sanity check before diving into manual exploitation, RsaCtfTool automates dozens of RSA attacks against a key or raw parameters.
RsaCtfTool queries factordb.com automatically. If your modulus is in the database, the tool recovers the flag without any further configuration. Run it first, then read the output to understand which attack succeeded before moving on.

SageMath for Advanced Attacks

For challenges that require lattice-based attacks (Coppersmith’s method, partial key exposure), SageMath is your best option. It ships with everything you need.

Quick Reference

Last modified on July 23, 2026