Every HTTPS connection begins with a negotiation that has to solve an absurd-sounding problem: two parties who’ve never met, over a wire an attacker fully controls, must agree on a secret key and verify who they’re talking to — in one round trip, because milliseconds are money. TLS 1.3 (RFC 8446, 2018) is the cleanest answer cryptography has shipped, mostly because of what it removed. Knowing its moving parts is the difference between debugging certificate errors by ritual and by reading.
One Round Trip, Three Jobs
ClientHello ──▶ supported versions/ciphers, SNI,
+ ECDHE key share (a guess, sent upfront)
◀── ServerHello (chosen cipher, server's key share)
── everything below already encrypted ──
◀── EncryptedExtensions, Certificate,
CertificateVerify, Finished
Finished ──▶ application data flowsJob 1 — key agreement is ephemeral Diffie-Hellman (X25519 in practice): each side contributes a fresh keypair, both derive the same shared secret, an eavesdropper recording everything learns nothing. The 1.3 trick for speed: the client sends its key share speculatively in the first flight, gambling the server will accept X25519 (it will), collapsing 1.2’s two round trips into one. Note what’s gone: RSA key transport — 1.2’s mode where the client encrypted the secret to the server’s long-term key — which meant one leaked server key retroactively decrypted every recorded session. Ephemeral-only means forward secrecy is mandatory, and an entire class of both attacks and passive-decryption middleboxes died with it (enterprises now run explicit MITM proxies instead — at least the model is honest).
Job 2 — authentication rides the certificate chain: the server sends
its cert plus intermediates; the client builds a path to a trusted root,
checks names (SNI in, SAN out — CN has been dead for years), validity
windows, and signatures; then — the step people forget exists —
CertificateVerify: the server signs the handshake transcript with the
certificate’s private key, proving it actually holds it. Without that, a
certificate is just a public document anyone could replay.
Job 3 — integrity of the negotiation itself: both Finished messages
MAC the entire transcript, so a middlebox stripping strong ciphers from
the ClientHello (the downgrade attacks that plagued 1.2 — FREAK, Logjam)
breaks the handshake. 1.3 also encrypts everything after the ServerHello,
so certificates travel encrypted — network observers get SNI (until ECH
lands widely) and little else.
Resumption, and the 0-RTT Footgun
Reconnecting clients get session tickets (PSKs) and skip certificate work — cheap and uncontroversial. The controversial gift is 0-RTT: sending application data in the first flight, encrypted under the resumed key, before any server response. Free latency — and structurally replayable: an attacker can capture the flight and deliver it again; no handshake-completion proof protects it. Safe only for idempotent requests, which is why serious deployments restrict it (CDNs allow GETs without bodies and reject the rest with 425 Too Early) and why “we enabled 0-RTT globally” belongs in a risk review, not a performance PR.
Where It Actually Breaks
Production TLS failures cluster in unglamorous places, none of them the
cryptography: incomplete chains (server sends leaf without
intermediate — works in browsers that cache/fetch intermediates, fails in
curl/openssl/your language runtime; the source of “works in Chrome,
fails in prod” forever; openssl s_client -connect host:443 -servername host shows exactly what’s sent), expiry (monitor -enddate
programmatically; outages by calendar are self-inflicted), name
mismatches (SNI-less clients hitting multi-cert servers get the default
cert), and trust-store drift (containers FROM scratch, old CA bundles
— ask the box, not the spec: curl -v names the failing step). The
debugging kit is three commands deep: openssl s_client (handshake
transcript + chain), openssl x509 -text (read the cert), and your
load balancer’s config, because TLS terminates there and the backend hop
is a separate security decision people forget to make.
Takeaways
- 1.3 = one round trip: speculative ECDHE share, chain + transcript signature for identity, transcript MAC against downgrade.
- Forward secrecy is mandatory now — key compromise no longer decrypts history; passive-decrypt middleboxes are extinct by design.
- CertificateVerify is why possession is proven, not just presented; everything after ServerHello travels encrypted.
- 0-RTT data is replayable by construction — idempotent requests only, enforced, or leave it off.
- Real-world failures: chains, expiry, SNI/SAN, trust stores — all legible via openssl s_client before anyone blames the crypto.