Chapter 2 · Cryptography· Intermediate· ~18 min

TLS & PKI

Inside the TLS 1.3 handshake: the key schedule, 0-RTT trade-offs, certificate transparency, and mutual TLS.

You will learn

  • What each TLS 1.3 message actually carries and which messages are encrypted
  • How the key schedule derives every key in the handshake from one shared secret
  • What 0-RTT gives you, what it costs you, and when not to enable it
  • What Certificate Transparency provides and what it does not
  • Where mutual TLS earns its keep

The 1-RTT handshake, message by message

A TLS 1.3 connection completes in one round trip. The exchange:

  1. Client to server: ClientHello. Contains supported cipher suites, the client's key_share (an ephemeral ECDH public key), the SNI hostname, supported signature algorithms, and a random nonce.
  2. Server to client: ServerHello. Picks the cipher suite and the server's matching key_share. From this point the connection has a handshake-traffic key.
  3. Server to client (encrypted): EncryptedExtensions, Certificate, CertificateVerify (a signature over the transcript using the certificate's private key), Finished (an HMAC over the transcript using the handshake key).
  4. Client validates the chain, the SCTs, and the signature.
  5. Client to server (encrypted): Finished.
  6. Both: application-traffic keys are derived; encrypted application data flows.

Compared to TLS 1.2, the certificate is encrypted under the handshake key, the cipher suite list is much shorter (only AEAD suites remain), and the handshake completes one round trip earlier.

The key schedule

TLS 1.3 derives every key from a single shared secret using HKDF. The conceptual chain:

  • early_secret = HKDF-Extract(salt=0, PSK or 0)
  • handshake_secret = HKDF-Extract(salt=Derive(early_secret), IKM=ECDH shared)
  • master_secret = HKDF-Extract(salt=Derive(handshake_secret), IKM=0)

From each secret, HKDF-Expand-Label produces specific keys: client/server handshake traffic key, client/server application traffic key, exporter master secret, resumption master secret. The labels mix in a transcript hash so different parts of the handshake never share key material.

0-RTT and its trade-offs

Once a connection is established, the server can issue a session ticket with a PSK. On the next connection the client may attach early data encrypted under that PSK, alongside its ClientHello. This is "0-RTT": application data arrives in the first flight.

The cost:

  • Replay. The early data has no anti-replay protection at the TLS layer. Anyone who captures it can replay it. Servers must treat 0-RTT requests as idempotent.
  • Forward secrecy. Early data is protected by the PSK, not by the fresh ECDH. If the PSK leaks later, the early data is decryptable retroactively.

Right call: enable 0-RTT for safe GET requests only, disable for anything mutating, log it clearly. Many servers default to off.

The HSTS escape valve

If a client has visited a site over TLS and the server returned an HSTS header, the browser refuses to downgrade to HTTP for the lifetime of the policy. The preload list bakes this in before the first visit for major sites. HSTS preload is the right way to harden a public site.

Certificate Transparency

Browsers refuse to trust a publicly trusted certificate unless it appears in append-only public CT logs. Each log entry produces a Signed Certificate Timestamp (SCT), which the certificate or the TLS handshake must carry.

What CT actually buys you:

  • Mis-issuance becomes visible. A CA that issues a certificate for a domain it should not have can be caught by anyone running a log monitor.
  • You can subscribe to certificates issued for your own domains and notice unauthorized issuance within minutes.

What CT does not buy you: it does not prevent issuance, only makes it visible. A CA that issues a malicious cert and submits it to the log still issued it.

OCSP, OCSP stapling, and the must-staple gambit

Revocation in TLS is historically painful: CRLs are big, OCSP requests leak the visited site to the CA, and clients often fail open if revocation lookup fails. OCSP stapling moves the check to the server, which periodically fetches a signed OCSP response and includes it in the TLS handshake. OCSP Must-Staple is an X.509 extension that tells clients to refuse the connection if the staple is missing, closing the fail-open hole.

Mutual TLS

Standard TLS authenticates the server. mTLS additionally authenticates the client with a client certificate. It is the right tool for service-to-service authentication inside a zero-trust network: every service holds its own short-lived certificate signed by an internal CA, and every service refuses connections without a valid client cert.

mTLS is overkill for end users (issuing and revoking per-user certs is operational pain), but understated for service mesh, IoT, and inter-bank APIs.