The key distribution problem
Symmetric cryptography has a bootstrapping problem: to encrypt securely, both sides need the same secret key — but how do you get that key to the other side without an eavesdropper intercepting it first?
Public-key (asymmetric) cryptography, introduced conceptually by Diffie and Hellman in 1976 and made practical by Rivest, Shamir, and Adleman with RSA in 1977, solves this with two mathematically linked keys: a public key anyone can know, and a private key only the owner holds. Data encrypted with the public key can only be decrypted with the matching private key.
How RSA works, at a glance
RSA's security rests on a simple asymmetry: multiplying two large prime numbers is easy, but factoring their product back into the original primes is computationally hard for classical computers when the numbers are large enough (2048 bits or more, today).
Key generation picks two large random primes p and q, computes n = p × q, and derives a public exponent e and private exponent d such that they're mathematically inverse under modular arithmetic tied to n. The public key is (n, e); the private key is (n, d). Encryption raises the message to the power e mod n; decryption raises the ciphertext to the power d mod n.
In practice, RSA is rarely used to encrypt bulk data directly — it's slow and has strict size limits. Instead it's typically used to encrypt a short symmetric key (key transport) or to produce digital signatures, with AES doing the heavy lifting on the actual data.
RSA key generation, encryption, and decryption
- 1
Generate keys
Pick large random primes p, q. Compute n = pq and φ(n) = (p−1)(q−1). Choose e coprime to φ(n), then derive d as e's inverse mod φ(n).
- 2
Publish the public key
(n, e) is shared openly. (n, d) — the private key — never leaves the owner.
- 3
Encrypt
Anyone computes C = Mᵉ mod n using only the public key.
- 4
Decrypt
Only the private-key holder computes M = Cᵈ mod n to recover the message.
n is the modulus; φ(n) (Euler's totient) is only computable if you know p and q.
The public exponent e and private exponent d are chosen to be modular inverses of each other.
Encryption with the public key (n, e); decryption with the private key (n, d).
A worked example with small numbers
Real RSA uses primes hundreds of digits long, but the same arithmetic works identically with small ones — which is why this toy example (the one most textbooks use) is worth stepping through by hand.
Take p = 61 and q = 53. Then n = 3233 and φ(n) = 60 × 52 = 3120. Pick e = 17 (it shares no common factors with 3120). Solving 17d ≡ 1 (mod 3120) gives d = 2753 — that's the whole key pair: public key (3233, 17), private key (3233, 2753).
Encrypting the message M = 65 gives C = 65¹⁷ mod 3233 = 2790. Decrypting runs it back: 2790²⁷⁵³ mod 3233 = 65. The same modulus, two different exponents, one direction easy without the private key and the other only possible with it.
Finding d: the extended Euclidean algorithm
Solving "17d ≡ 1 (mod 3120)" isn't guesswork — it's a standard computation called the extended Euclidean algorithm, which finds the modular inverse of e directly. Run backward, the ordinary Euclidean algorithm (repeated division to find a greatest common divisor) leaves behind a trail of remainders; the extended version tracks coefficients alongside those remainders and, because e and φ(n) were chosen to be coprime, that trail terminates in exactly the d you need. It's fast — logarithmic in the size of the numbers — which is what makes key generation practical even for 2048-bit primes.
Why e = 65537 shows up everywhere
Almost every RSA key you'll encounter uses the public exponent e = 65537, and the reason is a genuine engineering trade-off rather than convention. Written in binary, 65537 is 10000000000000001 — only two bits are set — and the square-and-multiply algorithm used for modular exponentiation does one multiplication per bit and one extra squaring per set bit, so a sparse exponent like this makes encryption and signature verification (both of which use e) noticeably faster than a dense one would.
Smaller exponents like e = 3 are even faster, but they reopen exactly the kind of low-exponent attacks covered below — 65537 is small enough to stay fast and large enough to close off the simplest ones. It also happens to be a Fermat prime (2¹⁶ + 1), which guarantees it's coprime with φ(n) for essentially any RSA modulus, simplifying key generation.
RSA signatures: the same math, opposite roles
Encryption and signing use identical RSA arithmetic with the public and private key's roles reversed. To encrypt, anyone raises a message to the public exponent; to sign, the key-holder raises a (hashed) message to their private exponent — something only they can do. To decrypt, the key-holder raises the ciphertext to their private exponent; to verify a signature, anyone raises it to the public exponent and checks the result matches the message's hash.
In practice, following the hash-then-sign pattern from the hashing module, RSA never signs a raw message directly — it signs a padded hash digest (via RSA-PSS, covered in the padding module), for exactly the same reasons raw RSA encryption is unsafe.
What can go wrong: classic implementation attacks
RSA's math is sound; most real-world breaks come from how it's deployed. Three patterns recur across decades of RSA vulnerabilities, and none of them require factoring anything.
RSA pitfalls that have nothing to do with factoring
Common modulus attack
If two users are (incorrectly) issued the same n with different e values, anyone who intercepts the same message encrypted to both can recover it algebraically — without ever factoring n.
Håstad's broadcast attack
The same message sent to several recipients using a small e (like 3) and different moduli can be recovered using the Chinese Remainder Theorem, entirely bypassing the private keys.
Weak randomness in key generation
If the "random" primes p and q aren't actually independent and unpredictable, keys across different devices can end up sharing a prime factor — a real issue found in some embedded devices' RSA key generation.
Why factoring is the whole game
Every attack on RSA either tries to factor n directly or tries to find a shortcut that avoids factoring. The best known classical factoring algorithm, the General Number Field Sieve (GNFS), has sub-exponential running time — hard enough that factoring a 2048-bit RSA modulus is considered infeasible with any classical computer for the foreseeable future.
This is precisely the assumption that Shor's algorithm breaks on a sufficiently large quantum computer — see the quantum threat module for why RSA is on every PQC migration roadmap.
The factoring record, over time
RSA-100 (330 bits)
Factored in 1991.
RSA-129 (426 bits)
The modulus from the original 1977 RSA challenge — factored in 1994, using idle computer time volunteered over the internet.
RSA-768 (768 bits)
Factored in 2009, after roughly two years of computation across many machines.
RSA-2048 (2048 bits)
Today's minimum recommended size — still unfactored, and expected to stay that way classically for the foreseeable future.
GNFS's running time — sub-exponential, but still growing fast enough that doubling n's bit length costs far more than double the effort.