The Secret Handshake
When you see that padlock icon in your browser, it means all communication between you and the server is encrypted. But how do two strangers agree on encryption keys without an eavesdropper stealing them? That is what the TLS handshake solves.
Think of it like two spies who need to communicate but are in a room full of listeners. They need to agree on a secret code without anyone else figuring it out. Mathematically, this is possible - and it happens billions of times per second across the internet.
TLS 1.2 Handshake: The Full Process
Client Server
| |
|--- ClientHello -------------------> |
| (supported ciphers, random_C) |
| |
| <--- ServerHello ---------------- |
| (chosen cipher, random_S) |
| <--- Certificate --------------- |
| (server's public key) |
| <--- ServerHelloDone ----------- |
| |
|--- ClientKeyExchange ------------> |
| (pre-master secret, encrypted |
| with server's public key) |
|--- ChangeCipherSpec -------------> |
|--- Finished (encrypted) --------> |
| |
| <--- ChangeCipherSpec ----------- |
| <--- Finished (encrypted) ------ |
| |
|====== Encrypted data flows ========= |
Total: 2 round trips (2-RTT)
At 50ms latency = 100ms before first byte
Step by step: the client says 'Hi! I support these cipher suites and TLS versions, and here is a random number I generated.' The server responds with 'Let us use this cipher, here is my random number and my digital certificate.' The browser verifies the certificate is signed by a trusted Certificate Authority, has not expired, and matches the domain. Then the browser generates a pre-master secret, encrypts it with the server's public key, and sends it. Only the server's private key can decrypt it. Both sides derive session keys from the shared secrets, and the encrypted tunnel is established.
TLS 1.3: Faster and Safer
TLS 1.3, released in 2018, is a major improvement that every modern system should use:
TLS 1.2: 2 round trips
ClientHello -> ServerHello + Certificate -> KeyExchange -> Done
|--- RTT 1 ---|------- RTT 2 ------|
TLS 1.3: 1 round trip
ClientHello + KeyShare -> ServerHello + Certificate + Finished
|---------- RTT 1 ----------|
TLS 1.3 (0-RTT resumption): 0 round trips
ClientHello + EarlyData (encrypted with previous session key)
|--- Data flows immediately! ---|
- 1-RTT handshake - reduced from 2 round trips to 1 by sending key exchange data in the first message
- 0-RTT resumption - if you connected to this server before, you can send encrypted data in your very first packet (with a caveat: 0-RTT data can be replayed, so only use it for idempotent requests like GET)
- Removed unsafe algorithms - no more RSA key transport, no CBC ciphers, no SHA-1. Only modern, proven cryptography.
- Forward secrecy mandatory - even if the server's private key is stolen in the future, past conversations remain safe because each session uses unique ephemeral keys
Why Forward Secrecy Matters
In TLS 1.2, if an attacker recorded your encrypted traffic AND later stole the server's private key, they could decrypt everything retroactively. Forward secrecy prevents this. Each connection generates unique ephemeral keys that are thrown away after use. Even with the private key, old sessions cannot be decrypted. This matters enormously when you consider that nation-state attackers routinely record encrypted traffic hoping to decrypt it later.
Why This Matters for System Design
The TLS handshake adds latency to every new connection. At scale, this matters enormously:
- Connection pooling - keep TLS connections alive and reuse them instead of handshaking for every request. A pool of 50 persistent connections eliminates 50 handshakes.
- Edge termination - terminate TLS at CDN edge nodes close to users (reducing round-trip distance) then use plain HTTP or mutual TLS to your origin servers internally. This cuts user-perceived handshake latency by 60-80%.
- Session tickets - allow clients to resume previous TLS sessions without a full handshake. Most browsers support this.
- Certificate optimization - use ECDSA certificates (smaller, faster) over RSA. A 256-bit ECDSA key provides equivalent security to a 3,072-bit RSA key but the handshake is 3-4x faster. Use OCSP stapling to avoid the browser making a separate call to check certificate revocation.
Common Mistakes in Production
- Forgetting to enable TLS 1.3 on your load balancer - many default to TLS 1.2 only, leaving performance on the table
- Letting certificates expire - this causes a complete outage. Automate renewal with Let's Encrypt or your CA's API.
- Terminating TLS at every hop in a microservices mesh - each hop adds latency. Terminate once at the edge or use mutual TLS (mTLS) with session resumption.
- Not monitoring certificate expiry - set alerts for 30, 14, and 7 days before expiry. Every major outage post-mortem has at least one 'expired certificate' example.
Numbers That Matter
- TLS 1.2 handshake: ~100ms at 50ms latency (2 RTT)
- TLS 1.3 handshake: ~50ms at 50ms latency (1 RTT)
- TLS 1.3 with 0-RTT: ~0ms additional latency for returning visitors
- ECDSA certificate verification: ~0.1ms vs RSA at ~1ms
- A typical web server can handle 1,000-5,000 new TLS handshakes per second per CPU core
- Let's Encrypt issues ~4 million certificates per day, all free and automated
Interview Tip
When discussing HTTPS in interviews, mention where you terminate TLS (edge vs origin) and why. Say: 'I would terminate TLS at the CDN edge to minimize handshake latency for users, then use mutual TLS between internal services for zero-trust security.' Bonus: mention that you would use TLS 1.3 to cut handshake time in half and enable 0-RTT for repeat visitors.
Key Takeaway
TLS encrypts all communication but adds latency due to the handshake. TLS 1.3 halved that latency and made forward secrecy mandatory. When architecting systems, minimize handshakes through connection reuse, edge termination, and session resumption. Always automate certificate management.