🔒 TLS, End to End

The layer that turns a cleartext transport into a private, tamper-proof, authenticated channel — and negotiates which protocol runs on top.

What TLS Actually Guarantees

TLS wraps a transport (almost always TCP; QUIC embeds it) and provides three things:

The clever part: asymmetric crypto (slow) is used only to agree on a shared symmetric key. Bulk data then uses that symmetric key (fast). This "hybrid" design is the whole game.

The Handshake (TLS 1.3)

TLS 1.3 completes in one round trip. The client speculatively sends a key share in its very first message, so the server can derive keys immediately.

sequenceDiagram participant C as Client participant S as Server C->>S: ClientHello + key_share + ALPN + SNI Note over S: Picks cipher, derives keys S->>C: ServerHello + key_share S->>C: {Certificate + CertVerify + Finished} Note over C: Verifies cert chain, derives keys C->>S: {Finished} C->>S: {Application data} — 1 RTT total
TLS 1.2 was slower: it needed two round trips (separate key-exchange step) before data could flow. Stacked on TCP's own handshake, that meant 3 RTTs before the first byte. TLS 1.3 halved it.

0-RTT Resumption

On a repeat connection to a known server, TLS 1.3 can send application data in the very first flight using a pre-shared key from the prior session — 0-RTT.

0-RTT is replayable. An attacker can capture and resend the early data. Only use it for idempotent requests (a GET), never for anything that mutates state.
QUIC leans on this hard: because QUIC folds the TLS 1.3 handshake into its transport handshake, a resumed HTTP/3 connection can reach 0-RTT — request data on the first packet. That's a big part of HTTP/3's latency story.

ALPN — Choosing the Protocol Above

Application-Layer Protocol Negotiation is a TLS extension that decides, during the handshake, which protocol runs on the encrypted connection — no extra round trip.

# See the negotiated protocol and TLS version
openssl s_client -connect example.com:443 -alpn 'h2,http/1.1' </dev/null \
  | grep -E 'ALPN|Protocol'
# ALPN protocol: h2
# Protocol  : TLSv1.3
ALPN idProtocol
http/1.1HTTP/1.1
h2HTTP/2 over TLS
h3HTTP/3 over QUIC
Why this matters: HTTP/2 is negotiated via ALPN, not a URL scheme. There's no h2://. The browser asks for h2; if the server agrees, you speak HTTP/2. This is also how a client discovers it can attempt HTTP/3.

The Chain of Trust

A certificate is only as good as who signed it. Verification walks a chain from the server's leaf cert up to a root CA your OS/browser already trusts.

flowchart TB R["Root CA
(in your trust store)"] --> I["Intermediate CA
(signed by root)"] I --> L["Leaf cert
example.com
(signed by intermediate)"] L --> V{"Client checks:
signature valid?
not expired?
SNI matches SAN?
not revoked?"}

The client validates, in order:

Common failure: serving the leaf cert but forgetting the intermediate. Browsers may cache the intermediate and "work for me," while fresh clients fail to build the chain. Always serve the full chain except the root.

Inspecting a Handshake

# Full certificate chain + negotiated params
openssl s_client -connect example.com:443 -servername example.com -showcerts

# Just the cert's identity and validity
echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
Forward secrecy: TLS 1.3 mandates ephemeral Diffie-Hellman, so each session gets a unique key. Even if the server's long-term private key later leaks, past recorded traffic stays unreadable. Older RSA key-exchange suites didn't have this — capturing traffic + a future key leak decrypted everything.

Key Takeaways