Changes

Chapter 7
TLS 1.3 — What Changed
A 1-RTT handshake, 0-RTT resumption, and the great purge of legacy crypto

TLS 1.3 (standardized 2018) is the version your browser uses for almost every modern HTTPS connection. It isn't a tweak of 1.2 — it's a redesign driven by two goals: make the handshake faster and make it safe by default by deleting every legacy option that caused trouble. This chapter contrasts it directly with the 1.2 handshake from Chapter 6.

Change 1: The Handshake Is Now 1-RTT

The big insight: in 1.2, the client waited for the server to choose parameters before it could contribute its key-exchange share — costing a round trip. TLS 1.3 removes the suspense. Since modern key exchange is always ephemeral (EC)DHE, the client guesses the key-exchange group and sends its DH share immediately, in the ClientHello:

CLIENTSERVER
— round trip 1 —
ClientHello + key_share (DH value)
ServerHello + key_share
{Certificate, CertVerify, Finished}🔒
— client can now send data —
{Finished}🔒 + 🔒 Application Data

By the time the server responds once, both sides already share the secret — so the server can send its Certificate, signature, and Finished already encrypted in that same flight, and the client can send application data right after its own Finished. One round trip instead of two. (The { } braces mark messages that are now encrypted; note the certificate itself is encrypted in 1.3, unlike 1.2 where it was sent in the clear.)

"Guessing" the group costs nothing in the common case
The client guesses the most common group (usually X25519) and sends a share for it. Almost always the server supports it and the guess is right → 1-RTT. If the server wants a different group, it replies with a HelloRetryRequest asking the client to resend with the right group — falling back to 2-RTT for that one connection. Because the popular groups are near-universal, the retry is rare, so the common case is a clean single round trip.

Change 2: 0-RTT Resumption (with a caveat)

For a server you've connected to before, TLS 1.3 can do even better. Using a pre-shared key (a session ticket) from the previous connection, the client can send encrypted application data in its very first message — zero round trips of waiting. This "0-RTT early data" makes repeat visits feel instant. But it comes with a sharp security trade-off:

0-RTT early data is replayable — not for everything
0-RTT data is not protected against replay attacks: an attacker who captures the encrypted early-data packet can resend it, and the server may process it again, because there's no fresh server randomness involved yet. That's harmless for an idempotent GET /article, but dangerous for a non-idempotent action like "transfer $100" or "place order," which must never run twice. So 0-RTT is restricted to safe, idempotent requests, and forward secrecy doesn't fully apply to that early-data portion. It's an opt-in performance feature with real caveats — use deliberately, not blindly.

Change 3: Legacy Crypto Was Removed, Not Just Discouraged

TLS 1.2's flexibility was also its weakness: it still permitted weak options, and many real attacks (downgrade attacks, padding-oracle bugs) exploited them. TLS 1.3's most consequential security move was to delete the dangerous options entirely, so they can't be negotiated even by mistake:

Removed in TLS 1.3Why it was dangerous
RSA key transportno forward secrecy (Chapter 3's "harvest now, decrypt later")
Static (non-ephemeral) DHalso lacked forward secrecy
CBC-mode & RC4 cipherspadding-oracle & keystream-bias attacks (BEAST, Lucky13, etc.)
Plain (non-AEAD) cipher modesencryption without built-in integrity
MD5 / SHA-1 signaturesbroken / collision-prone hash functions
Renegotiation, compressionenabled attacks like CRIME

What's left is a short, curated list: only AEAD ciphers (AES-GCM, ChaCha20-Poly1305), only ephemeral (EC)DHE key exchange, and modern hashes. There's no weak option to downgrade to. This is the deepest lesson of the chapter: 1.3 is safer not because it added cleverness, but because it removed choices. Forward secrecy went from "available if configured" (1.2) to "mandatory and unavoidable" (1.3).

Change 4: The Cipher Suite Got Simpler

In 1.2, a cipher suite string bundled four choices together: key exchange + authentication + bulk cipher + hash (e.g. ECDHE-RSA-AES128-GCM-SHA256). In 1.3, key exchange and authentication are negotiated separately, so a "cipher suite" now names only the bulk AEAD cipher and its hash:

# TLS 1.2 suite — bundles everything ECDHE-RSA-AES128-GCM-SHA256 \___/ \_/ \_________/ \____/ kex auth cipher hash # TLS 1.3 suite — just the AEAD cipher + hash (kex/auth handled separately) TLS_AES_128_GCM_SHA256

This is why TLS 1.3 has only a handful of cipher suites instead of hundreds — Chapter 8 reads these strings in detail.

TLS 1.2 vs 1.3 at a Glance

TLS 1.2TLS 1.3
Handshake latency2-RTT1-RTT (0-RTT on resume)
Forward secrecyoptionalmandatory (always ephemeral)
RSA key transportallowedremoved
Cipher modesAEAD + legacy CBC/RC4AEAD only
Certificate sentin the clearencrypted
Cipher suite counthundredsfive

In practice you rarely configure any of this — modern servers and browsers negotiate TLS 1.3 automatically and fall back to 1.2 only for older peers. But understanding what changed explains why "just use the defaults" is now genuinely safe advice, which it wasn't a decade ago. The next chapter zooms into reading and choosing the cipher suites and protocol versions themselves.

Hands-On Exercises

Exercise 1

Connect to the same server twice — once with -tls1_3 and once with -tls1_2 using openssl s_client ... -msg — and compare the message flows. Identify which messages disappear or move in 1.3, and confirm the certificate is encrypted in 1.3 but not 1.2.

📄 View solution
Exercise 2

Explain why TLS 1.3 can achieve 1-RTT when 1.2 needed 2-RTT. Be specific about what the client sends in the ClientHello that it couldn't before, and what assumption makes that possible (and what happens via HelloRetryRequest when the assumption is wrong).

📄 View solution
Exercise 3

For each request, decide whether it would be safe to send as 0-RTT early data and justify it: (a) GET /news/today; (b) POST /transfer?amount=500; (c) GET /account/balance; (d) POST /comments adding a comment. State the general rule you're applying.

📄 View solution

Chapter 7 Quick Reference

  • TLS 1.3 (2018) — faster and safe-by-default; a redesign, not a tweak of 1.2
  • 1-RTT handshake — client sends its (EC)DHE key_share in the ClientHello, so the secret exists after one round trip
  • HelloRetryRequest — fallback to 2-RTT when the client guessed the wrong key-exchange group (rare)
  • The certificate is encrypted in 1.3 (it was in the clear in 1.2)
  • 0-RTT resumption — repeat visits send early data with zero wait, but it's replayable → only for idempotent requests
  • Legacy crypto removed: RSA key transport, static DH, CBC/RC4, non-AEAD, MD5/SHA-1, renegotiation, compression
  • Safer because it removed choices — only AEAD ciphers + ephemeral (EC)DHE remain; forward secrecy is mandatory
  • 1.3 cipher suites name only AEAD cipher + hash (e.g. TLS_AES_128_GCM_SHA256) — kex/auth negotiated separately
  • Next chapter: cipher suites & protocol versions — reading the strings and what to enable/disable