The idea: a shared secret from public messages
Alice and Bob have never met and share no secret. Everything they send can be read by Eve. With Diffie-Hellman key exchange (1976) they still end up with the same secret number, which Eve cannot compute. They then use it as the key of a fast symmetric cipher. Every HTTPS, SSH and WireGuard connection starts this way.
The canvas has three regions: Alice on the left, the public channel in the middle and Bob on the right. Red values are private and never leave their owner. Blue packets are public. Eve's notebook in the middle lists exactly what crossed the wire.
The math with p = 23, g = 5
- In public, both agree on a prime
p = 23and a baseg = 5. - Alice picks a private
a = 6, Bob a privateb = 15. - Alice sends
A = ga mod p = 56 mod 23 = 8. Bob sendsB = gb mod p = 515 mod 23 = 19. - Alice computes
s = Ba mod p = 196 mod 23 = 2. Bob computess = Ab mod p = 815 mod 23 = 2.
Both get the same number because (gb)a = gab = (ga)b, and that stays true mod p. To show the key in use, Alice then shifts each letter of HELLO BOB by 2 and sends JGNNQ DQD (Demo: key exchange). Real TLS feeds s into HKDF and derives AES-GCM or ChaCha20 keys.
| Value | Alice | Bob | Eve |
|---|---|---|---|
p = 23, g = 5 | ✓ | ✓ | ✓ |
a = 6 | ✓ | ✗ | ✗ |
b = 15 | ✗ | ✓ | ✗ |
A = 8, B = 19 | ✓ | ✓ | ✓ |
s = 2 | ✓ | ✓ | ✗ (unless she solves a discrete log) |
Square-and-multiply
Nobody computes 515 in full. The exponent is read in binary from the left. For each bit the running value is squared, and for a 1-bit it is also multiplied by the base, reducing mod p after each step. For 56: 6 = 110₂, so 1²·5 = 5, 5²·5 = 125 ≡ 10, 10² = 100 ≡ 8. A 2048-bit exponent needs about 2048 squarings, which takes well under a millisecond. The bottom band of the canvas writes out every trace. The same method drives RSA: Modular Exponentiation and Toy RSA.
What Eve sees: the discrete logarithm
To get s, Eve needs a or b: an x with 5x ≡ 8 (mod 23). This is the discrete logarithm problem. For p = 23 she just tries 5, 2, 10, 4, 20, 8 and finds x = 6 after six tries (Demo: Eve breaks a tiny p). Any x that gives A works, even if it is not Alice's real a. In practice p has 2048 bits or more (RFC 7919 groups), or the exchange runs on an elliptic curve such as X25519 with 256-bit numbers. The best known algorithms then need far more work than anyone can do. Breaking DH is believed to be as hard as computing discrete logs, but that has not been proved.
The base matters too. g = 22 ≡ −1 has order 2: its powers are only 22 and 1. Every key is then 1 or 22, and Eve finds one in two tries (Demo: a weak generator g = 22). Real groups use a safe prime p = 2q + 1 and a g of large prime order q, and each side checks that the share it receives is not 0, 1 or p − 1.
Man in the middle
Plain DH proves nothing about who is on the other end. Mallory, who can change packets, catches A and sends Bob his own share M = 59 mod 23 = 11, and does the same to B on the way back. Alice ends up with key 116 mod 23 = 9, shared with Mallory. Bob ends up with 1115 mod 23 = 10, also shared with Mallory. Mallory decrypts Alice's message with 9, reads it, encrypts it again with 10 and forwards it. Both exchanges are mathematically correct, so neither side notices (Demo: man in the middle).
How TLS signs the share (ECDHE)
In TLS the server signs the key exchange with the private key of its certificate. TLS 1.2 signs the ServerKeyExchange message. TLS 1.3 signs a hash of the whole handshake transcript in CertificateVerify. The client checks that signature with the public key in the certificate, after checking the certificate chain (TLS Certificate Chain). In the page, Bob signs the pair he saw, (A = 11, B = 19). Alice checks it against the pair she saw, (A = 8, B = 11), and it fails. Mallory cannot make a signature with Bob's key, so the handshake stops (Demo: signed DH share stops MITM). How the signature arithmetic works is on How a Digital Signature Works. The full handshake is on How an HTTPS Connection Is Established.
TLS 1.3 only allows ephemeral exchanges: ECDHE (elliptic-curve DH, usually X25519 or P-256) or DHE, with new private numbers for every connection that are deleted afterwards. This gives forward secrecy. A server key stolen later can be used to impersonate the server, but it cannot decrypt sessions recorded earlier, because their keys came from a and b that no longer exist (Demo: fresh keys every session: s = 2, then s = 16). TLS 1.2's old RSA key transport had no such property.
| Plain DH | Signed (TLS) | |
|---|---|---|
| Eve (passive) | ✓ safe, if p is large | ✓ safe |
| Mallory (active) | ✗ reads everything | ✓ detected, handshake aborted |
| Needs beforehand | nothing | a trusted CA key (trust store) |
DH gives a shared key without any secret sent across. RSA encryption and hybrid encryption are compared in Symmetric vs Asymmetric Encryption. The modular inverses that RSA needs are on Extended Euclid and RSA.
What the page leaves out
Real sizes: 2048 to 4096-bit primes or 256-bit curves, and how elliptic-curve point multiplication replaces ga mod p. Index-calculus and number-field-sieve attacks, and the Logjam attack on 512-bit export groups. Key derivation (HKDF) and the AEAD cipher instead of the toy shift cipher. The actual signature arithmetic and certificate checks. Client authentication, and other ways to authenticate DH (pre-shared keys, SSH host keys, PAKEs). Post-quantum key exchange (ML-KEM, used together with X25519 in hybrid TLS 1.3 handshakes), since Shor's algorithm would break DH on a large quantum computer.