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

text
  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 flows

Job 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.