RSA and OAEP
RSA is the best-known public-key cryptosystem and a central example of trapdoor arithmetic. Public operations raise values to an exponent modulo . Private operations use knowledge of and to invert that exponent. The algebra is elegant, but textbook RSA is not secure encryption. Padding and security definitions are not optional details; they are the difference between a math function and a cryptographic scheme.
Katz and Lindell distinguish plain RSA, RSA assumptions, padded RSA, OAEP, CCA security, and implementation pitfalls. Smart gives complementary arithmetic examples, implementation notes, and public-key attack context. Taken together, they show why modern RSA encryption is normally used as a KEM or through standardized padding, not as on raw messages.
Definitions
RSA key generation:
- Choose large distinct primes .
- Set .
- Compute or .
- Choose public exponent with .
- Compute private exponent such that:
The public key is and the private key is together with often for efficient CRT computation.
The RSA function is:
The trapdoor inverse is:
The RSA assumption says that for appropriately generated and random , it is infeasible to find such that:
Textbook RSA encryption is:
It is deterministic and malleable, and therefore not CPA secure.
OAEP, Optimal Asymmetric Encryption Padding, is a randomized encoding method that uses hash-like masks before applying the RSA function. It is used in RSAES-OAEP and supports strong security proofs in the random-oracle model.
Key results
RSA correctness follows from Euler-style exponent arithmetic. Since , for :
The result extends to all residues modulo using CRT reasoning over and .
Textbook RSA is not secure. It is deterministic, so encrypting the same message twice gives the same ciphertext. It is also multiplicatively malleable:
For any , define:
Then:
An attacker can transform a ciphertext into an encryption of a related plaintext without knowing the message.
Small-exponent and small-message errors are also dangerous. If and , then as an ordinary integer, so the attacker can take an integer cube root. If the same message is sent to several recipients with and no padding, CRT can recover the message.
OAEP addresses determinism and structure by encoding a message with randomness before RSA exponentiation. In simplified form, it uses two mask-generating functions and :
and RSA is applied to . Decoding reverses the masks and checks the padding. The exact standardized format includes lengths, labels, and error handling rules.
RSA decryption and signing implementations must resist side channels. Timing differences, padding-oracle behavior, fault attacks, and missing blinding have all mattered in practice. The mathematical proof assumes the adversary sees only allowed inputs and outputs, not power traces or detailed error codes.
Key generation has several quiet requirements. The primes and must be generated with high-quality randomness, be large enough, and not be too close together. The public exponent is often because it is efficient and avoids the worst small-exponent choices when combined with proper padding. The private exponent must not be unusually small; otherwise attacks such as Wiener's attack may apply. Implementations also store CRT parameters for speed, but those parameters are sensitive secret-key material.
OAEP's label field is often empty, but it is still part of the encoding. If a protocol uses a nonempty label, decryption must check the same label. This is another instance of context binding: the ciphertext should decrypt only in the context for which it was created. OAEP decoding must perform all checks in a way that does not reveal which check failed. Returning "bad seed," "bad label hash," and "bad delimiter" as separate errors would defeat the point of CCA-aware design.
RSA is now more common for signatures than for new encryption designs, and many modern protocols prefer elliptic-curve or post-quantum key exchange for establishing session secrets. Still, RSA remains important because of deployed certificates, legacy protocols, hardware support, and the conceptual clarity of trapdoor permutations. Understanding why textbook RSA fails is one of the best ways to learn why padding standards exist.
The relation between factoring and RSA inversion is subtle. Knowing and lets the holder compute and invert the public exponent. Therefore factoring breaks RSA. The reverse direction is not known to be equivalent in all formulations: an algorithm that inverts RSA on random inputs may or may not directly factor depending on assumptions and details. This is why textbooks state an RSA assumption separately from a factoring assumption.
For signatures, do not reuse encryption padding. RSA-OAEP is for encryption. RSA-PSS or carefully analyzed hash-and-sign variants are for signatures. The same trapdoor arithmetic underlies both, but the security experiments and encodings differ.
CRT optimization illustrates the tension between speed and robustness. Private RSA can compute modulo and modulo and recombine, often making operations several times faster. But if a fault corrupts only one branch during signing, the faulty signature may reveal a factor through a gcd computation. A defensive implementation can verify the final signature before output, use blinding, protect memory, and detect faults. The algebraic shortcut must be paired with implementation checks.
Blinding protects against timing and power leakage by randomizing the value before private exponentiation. For decryption, one can multiply the ciphertext by , exponentiate, and then remove afterward. The mathematical result is unchanged, but side-channel traces vary with fresh randomness rather than directly with the attacker's chosen ciphertext. This is another example where the textbook formula is correct but incomplete as an implementation recipe.
RSA ciphertext sizes are fixed by the modulus. A 2048-bit modulus produces 256-byte ciphertexts, regardless of whether the message being wrapped is a 32-byte session key. OAEP padding consumes some of that space for randomness and checks, so RSA encryption is naturally a key-wrapping or KEM-like tool rather than a bulk-data mechanism. Large data belongs in the symmetric DEM.
This size limit is another practical reason hybrid encryption is the default pattern.
Visual
| RSA variant | Randomized? | CPA secure? | Main issue |
|---|---|---|---|
| Textbook RSA | no | no | deterministic and malleable |
| RSA with ad hoc padding | maybe | not necessarily | parsing or oracle failures |
| RSAES-OAEP | yes | yes under ROM assumptions | must implement checks carefully |
| RSA-KEM | yes | can be CCA-secure with DEM | KDF and encapsulation details matter |
Worked example 1: toy RSA correctness
Problem: use , , , , public exponent . Find , encrypt , and decrypt.
Method:
- Find such that:
Since , .
- Encrypt:
Since , , so .
- Decrypt:
Use repeated squaring:
Since :
, , .
Checked answer: ciphertext , decrypted message .
Worked example 2: textbook RSA malleability
Problem: with the toy RSA key above, a ciphertext encrypts . Show that an attacker can create a ciphertext decrypting to without knowing .
Method:
-
Choose multiplier .
-
Compute the public RSA encryption of :
- Multiply the ciphertext:
- Decrypt algebraically:
- The target plaintext is:
Check with direct decryption:
Checked answer: decrypts to . Textbook RSA is malleable.
Code
def egcd(a, b):
if b == 0:
return a, 1, 0
g, x, y = egcd(b, a % b)
return g, y, x - (a // b) * y
def invmod(a, n):
g, x, _ = egcd(a, n)
if g != 1:
raise ValueError("no inverse")
return x % n
p, q = 5, 11
N = p * q
phi = (p - 1) * (q - 1)
e = 3
d = invmod(e, phi)
m = 7
c = pow(m, e, N)
print(N, e, d, c, pow(c, d, N))
print("malleated:", (c * pow(2, e, N)) % N)
Common pitfalls
- Calling textbook RSA encryption secure.
- Using deterministic or ad hoc padding.
- Forgetting that RSA encryption and RSA signatures need different padding schemes and different security arguments.
- Returning detailed OAEP padding errors.
- Using small messages with small exponents without randomized encoding.
- Implementing RSA private operations without blinding or CRT fault checks.