Chapter 09 // Primitives

Asymmetric
Encryption

Key exchange from Chapter 8 lets two parties create a shared secret. But what if you want to encrypt a message for someone you have never spoken to, someone who might not even be online? Public-key cryptography solves this: anyone can encrypt, but only the private key holder can decrypt.

Scroll to explore
01 // The Problem

Encryption for strangers

Chapters 1 through 7 assume both parties can establish a shared secret. But sometimes Alice needs to send a message that only Bob can read, with no prior contact at all.

The limitation of key exchange

Diffie-Hellman from Chapter 8 requires both parties to be online at the same time, exchanging messages back and forth. That works for a live TLS connection. It does not work for email, where the recipient might not check their inbox for hours. It does not work for encrypting a file to upload to a server. It does not work for any scenario where the sender and receiver are not simultaneously present.

Key exchange also creates a shared secret that both parties hold equally. There is no concept of “encrypt for Bob specifically.” Both Alice and Bob end up with the same key. If Alice wants to send a message to Bob and a different message to Charlie, she needs separate key exchanges with each, and each one requires both sides to participate in real time.

The mailbox idea

Imagine a mailbox with a slot. Anyone walking by can drop a letter in. But only the mailbox owner has the key to open it and read what is inside. The slot is public. The key is private. The two are completely separate.

If Bob publishes the equivalent of a mailbox address, Alice can encrypt a message that only Bob can decrypt. She does not need to meet Bob first. She does not need Bob to be online. She just needs his public key. This is asymmetric encryption: the encryption key (public) is different from the decryption key (private). It inverts the fundamental assumption of everything before it.

02 // The Concept

One-way functions with a secret shortcut

Asymmetric encryption needs a special kind of math: easy to compute forward, impossible to reverse, unless you know a secret. Try it yourself.

🔓

Public key = open padlock

Bob publishes open padlocks (his public key). Anyone can snap one shut on a box. Only Bob's key can reopen it.

🔑

Private key = the only key

Only Bob holds the private key. The ability to lock is completely separated from the ability to unlock.

🪤

Trapdoor function

The math that makes this possible: easy one way, hard to reverse. The secret (the trapdoor) is what makes decryption fast.

The Trapdoor: Multiply vs. Factor

Multiplying two primes is trivial. Factoring the product back? Try it yourself.

That asymmetry you just felt is the foundation of all public-key cryptography. For RSA, the trapdoor is integer factorization. For elliptic curve schemes, it is the Elliptic Curve Discrete Logarithm Problem from Chapter 8 (given a point on the curve, it is practically impossible to figure out how many times it was "added" to itself). Different math, same principle: easy forward, hard backward, fast with the secret.

03 // RSA

The first practical public-key system

Invented in 1977 by Rivest, Shamir, and Adleman. The factoring trapdoor you just experienced is exactly what RSA uses. Build a key pair step by step.

The core idea in two equations

Pick two secret primes, publish their product. Anyone can encrypt with the public key. Only the person who knows the primes can decrypt.

Encrypt (anyone)
c=memodnc = m^e \bmod n
Decrypt (private key holder)
m=cdmodnm = c^d \bmod n

ee (the public exponent) and dd (the private exponent) are mathematically linked. To find dd, you need to know ϕ(n)\phi(n) (the count of numbers less than n that share no common factors with n). Since ϕ(n)=(p1)(q1)\phi(n) = (p{-}1)(q{-}1), you can only compute it if you know the prime factors p and q. That is the trapdoor: factoring n is the hard part.

Build an RSA Key Pair

Walk through key generation step by step, then encrypt and decrypt a number. Change the primes and watch everything recalculate.

Choose prime p
Choose prime q
1
Multiply the primes to get the modulus
n=p×q=61×53=3233n = p \times q = {\color{#8b5cf6}61} \times {\color{#f59e0b}53} = 3233
2
Compute the totient (how many numbers from 1 to n share no common factors with n)
3
Pick public exponent e (must share no common factors with ϕ(n)\phi(n))
4
Compute private exponent d (the number where e * d wraps around to 1)
04 // Real RSA

RSA-OAEP in the browser

The demo above used tiny primes. Real RSA uses 2048-bit keys and requires OAEP padding to avoid the attacks in Section 08. Try it with the Web Crypto API.

🎲

OAEP adds randomness

“Textbook RSA” (memodnm^e \bmod n) is deterministic and malleable. OAEP mixes in random bytes before encryption, making identical messages produce different ciphertexts every time.

📏

Max 190 bytes

RSA-OAEP with a 2048-bit key and SHA-256 can encrypt at most 190 bytes. The modulus is 256 bytes, and OAEP padding consumes 66. You cannot encrypt a file, or even a long paragraph.

RSA-OAEP Encryption

Generate a real RSA key pair, encrypt a message with the public key, and decrypt it with the private key. Notice the size limitation: RSA-OAEP can only encrypt 190 bytes with a 2048-bit key.

05 // The Limitation

Too slow, too small

RSA encryption works. But it is roughly 1,000 times slower than AES-GCM and can only encrypt tiny amounts of data. These are not minor inconveniences. They make direct RSA encryption impractical for any real use case.

The performance gap

AES-GCM encrypts gigabytes per second. RSA-OAEP encrypts at most 190 bytes per operation, each taking milliseconds. A 10 MB file would need over 52,000 RSA operations. The solution is not a faster RSA. The solution is to use each for what it is good at.

AES-GCM vs. RSA-OAEP

Encrypt the same 128-byte payload 50 times with each algorithm. The performance difference explains why every real system uses hybrid encryption.

Iterations

This benchmark encrypts a tiny 128-byte payload. Real messages are kilobytes to megabytes. The gap only grows, because AES scales linearly while RSA cannot encrypt more than 190 bytes per operation.

The answer is obvious once you see the problem. Use asymmetric encryption for what it is good at (encrypting small secrets), and use symmetric encryption for what it is good at (encrypting bulk data). Combine them, and you get hybrid encryption.

06 // Hybrid Encryption

The pattern that powers the internet

Every real-world system that uses asymmetric encryption also uses symmetric encryption. Hybrid encryption combines both: RSA (or ECDH) encrypts a random AES key, and AES encrypts the actual data. TLS, PGP, and Signal all follow this pattern.

The hybrid pattern

Step 1: Generate a random 256-bit AES key (a “session key” or “data encryption key”).

Step 2: Encrypt the actual message with AES-GCM using that key.

Step 3: Encrypt the AES key with the recipient's RSA public key (RSA-OAEP). The AES key is only 32 bytes, well within the 190-byte limit.

Step 4: Send the RSA-encrypted key, the nonce, and the AES-encrypted message together.

To decrypt: use the RSA private key to recover the AES key, then use the AES key to decrypt the message.

Why this is strictly better

Speed. The bulk data is encrypted with AES, which is hardware-accelerated on most processors and orders of magnitude faster than RSA.

Size. No limit on message size. The RSA portion is always exactly one key (32 bytes), well within the OAEP limit.

Security. The symmetric key is random and single-use. Even if the same message is sent twice, the ciphertext is different because the AES key and nonce change.

Hybrid Encryption

RSA encrypts a random AES key. AES encrypts the actual message. The result: asymmetric encryption that works for messages of any size.

Exceeds RSA-OAEP limit of 190 bytes. Hybrid handles it.
1
Generate RSA-2048 key pair
2
Generate random AES-256 key
3
Encrypt AES key with RSA-OAEP
4
Encrypt message with AES-GCM
07 // ECIES

The modern approach

RSA-based hybrid encryption works but requires large keys and is slowly being displaced. ECIES (Elliptic Curve Integrated Encryption Scheme) achieves the same goal using the ECDH and AES primitives from earlier chapters, with smaller keys and better performance.

How ECIES works

1. The sender generates an ephemeral ECDH key pair (fresh for this message, discarded afterward).

2.Perform ECDH between the ephemeral private key and the recipient's long-term public key to produce a shared secret (raw bits).

3. Pass the shared secret through HKDF (a key derivation function that cleans up raw shared secrets into proper, uniformly random encryption keys) to derive an AES-GCM key.

4. Encrypt the message with AES-GCM using the derived key.

5. Send the ephemeral public key, nonce, and ciphertext. The recipient performs the same ECDH with their private key, derives the same AES key via HKDF, and decrypts.

Why ECIES over RSA

Smaller keys. A 256-bit ECDH key provides roughly 128-bit security, the same as a 3072-bit RSA key. Bob's public key is 65 bytes instead of hundreds.

Forward secrecy by default. Every message uses a fresh ephemeral key. Compromising the long-term private key does not reveal past messages, because each message used a different ephemeral key pair that no longer exists.

Faster. ECDH key generation and derivation are faster than RSA encryption. This is why modern protocols prefer elliptic curve constructions. TLS 1.3 uses ECDH. Signal uses X25519. The pattern is always: ephemeral key agreement, derive symmetric key, encrypt with AES.

ECIES Encryption (P-256)

Ephemeral ECDH + HKDF + AES-GCM. The sender generates a one-time key pair, derives a shared secret with the recipient's public key, feeds it through HKDF, and encrypts with AES-GCM. No RSA needed.

Bob (recipient)
Alice (sender)
Waiting for Bob's public key...

ECIES combines three primitives from earlier chapters: ECDH key exchange (Chapter 8), HKDF key derivation (a variation of HMAC from Chapter 3), and AES-GCM authenticated encryption (Chapter 6). This is a recurring theme in cryptography: complex systems are built by composing well-understood primitives.

08 // The Attacks

What goes wrong with RSA

RSA is correct in the mathematical sense. But using it correctly is surprisingly hard. Decades of attacks show that the gap between textbook RSA and secure RSA is enormous.

Textbook RSA is broken

Determinism: encrypting the same message twice produces identical ciphertext. An attacker who guesses a message can verify their guess by encrypting it with the public key and comparing.

Ciphertext manipulation: given E(m1) and E(m2), anyone can compute E(m1 · m2 mod n) without knowing m1, m2, or the private key. This allows ciphertext manipulation in predictable ways.

Bleichenbacher's padding oracle

Before OAEP, RSA used an older padding scheme. An attacker who can send modified ciphertexts to a server and observe whether the server reports “valid padding” or “invalid padding” can use that yes/no feedback to recover the entire plaintext, one byte at a time, in about one million queries.

This attack was used against real TLS implementations and is the reason the old padding has been deprecated. Always use OAEP.

Key size requirements

“N-bit security” means an attacker needs roughly 2^N operations to break the system. 112-bit security is considered safe today. 128-bit security provides an extra safety margin.

RSA-1024

Considered broken. Deprecated since 2013. Can be factored by well-resourced attackers.

RSA-2048

Current minimum. 112-bit security. Recommended by NIST for general use through 2030.

RSA-3072

128-bit security. Equivalent to AES-128 or P-256 ECDH.

P-256 ECDH

128-bit security with just 256-bit keys. 12 times smaller than the equivalent RSA key.

Textbook RSA Attacks

Without padding, RSA has two fundamental flaws that make it unsuitable for real use. Both are easy to demonstrate.

Fixed parameters: p=61, q=53, n=3233, e=17, d=2753
Message (2 to 3232)
42
First encryption
E(42)=4217mod3233=2557E(42) = 42^{17} \bmod 3233 = {\color{#ef4444}2557}
Second encryption (same message)
E(42)=4217mod3233=2557E(42) = 42^{17} \bmod 3233 = {\color{#ef4444}2557}
Identical ciphertexts

Same message, same ciphertext, every time. An attacker who guesses a message can verify their guess by encrypting it with the public key and comparing. With OAEP padding, random bytes are mixed in before encryption, so the same plaintext produces a different ciphertext each time.

09 // Real-World Usage

Asymmetric encryption in the wild

You encounter asymmetric encryption every time you open a browser, send an encrypted email, or use a messaging app. The implementations differ, but the core pattern is always hybrid encryption.

HTTPS and TLS certificates

Every HTTPS certificate contains a public key. When your browser connects to a website, the server presents its certificate. The browser verifies the server's identity using digital signatures (Chapter 10) and uses the certificate's public key as part of the authentication process.

TLS 1.3 uses ephemeral ECDH for key exchange, but the certificate's public key authenticates the server. The entire system is hybrid: asymmetric for authentication and key wrapping, symmetric for data encryption.

PGP and encrypted email

PGP generates a key pair for each user. To send an encrypted email: generate a random session key, encrypt the email body with AES, encrypt the session key with the recipient's public key, attach both. Classic hybrid encryption. How we verify that a public key actually belongs to the claimed person is the subject of Chapter 11.

Signal's sealed sender

Signal uses X25519 ECDH for key agreement, but its “sealed sender” feature takes it further: the message is encrypted so that even Signal's server cannot see who sent it. The sender's identity is encrypted inside the message using the recipient's public key.

This is asymmetric encryption solving a metadata problem, not just a content problem. The server relays the message without knowing the sender, because the sender information is inside the encrypted payload.

10 // Best Practices

Using asymmetric encryption correctly

Asymmetric encryption is a building block, not a complete solution. These guidelines reflect how modern protocols use it.

🔐

Always Hybrid Encrypt

Never encrypt data directly with RSA or any asymmetric scheme. Generate a random AES key, encrypt the data with AES-GCM, and encrypt the AES key with the recipient's public key. Every real system follows this pattern.

🛡️

Use OAEP Padding for RSA

RSA-OAEP with SHA-256 is the only safe RSA encryption padding. The older padding scheme is vulnerable to the padding oracle attack described in Section 08. If you must use RSA, always use OAEP.

Prefer ECIES Over RSA

ECIES with P-256 or X25519 gives you smaller keys, faster operations, and forward secrecy by default. RSA keys are 8 to 16 times larger for equivalent security, and lack forward secrecy without additional protocol design.

🚫

Never Roll Your Own

Use established libraries and protocols. The gap between textbook RSA and safe RSA is enormous: padding, key generation, and protection against timing attacks all matter. One mistake breaks everything.

The common thread: asymmetric encryption is always combined with symmetric encryption in practice. The asymmetric part handles the key distribution problem. The symmetric part handles the actual data protection. Never confuse the two roles.

11 // What You Learned

From shared keys to public keys

This chapter introduced the ability to encrypt for a specific recipient without any prior shared secret. Combined with the primitives from earlier chapters, you now have a complete encryption toolkit.

The story so far

Asymmetric encryption solves the “encrypt for a stranger” problem. A public key lets anyone create ciphertexts that only the private key holder can read.

RSA was the first practical solution, invented in 1977. Its security rests on the hardness of integer factorization, but it is slow and size-limited. Proper padding (OAEP) is essential to prevent determinism and malleability attacks.

Hybrid encryption makes asymmetric encryption practical: encrypt a random symmetric key with RSA (or ECDH), then encrypt the actual data with AES-GCM. Every real system uses this pattern.

ECIES is the modern approach: ephemeral ECDH + HKDF + AES-GCM. Smaller keys, forward secrecy by default, and faster than RSA. It combines primitives from Chapters 3, 6, and 7 into a single scheme.

You can now encrypt data for a specific person. But encryption alone does not prove who sent it. Anyone with Bob's public key can encrypt a message claiming to be Alice. Verifying the sender's identity requires digital signatures, the subject of Chapter 10. Signatures are the mirror image of encryption: instead of the public key encrypting and the private key decrypting, the private key signs and the public key verifies.

Up Next

Chapter 10 // Digital Signatures

Continue Learning