Octet

What is TLS 1.3 0-RTT, and why is it risky?

Show the answer

Say this first

0-RTT lets a client that has connected before send application data in its very first flight, encrypted with keys from a pre-shared key the server gave it in a session ticket. It saves a full round trip. The risk is replay: an attacker who captures the ClientHello and early data can send it again, and the server may process the request twice. Early data also lacks forward secrecy, because its keys come only from the ticket. So 0-RTT is only safe for idempotent requests, and many servers turn it off.

Go deeper

How it works

  1. In a previous connection, the server sent a NewSessionTicket.
  2. The new ClientHello carries pre_shared_key and early_data, followed by application data encrypted with the early traffic key.
  3. The server accepts by echoing early_data in EncryptedExtensions, or rejects it, in which case the client resends the data after the normal 1-RTT handshake.

Why replay is hard to stop

Within one server, single-use tickets or a cache of recent ClientHellos can catch duplicates. Across a cluster or many data centers, that state would have to be shared, so most deployments accept some replay window and limit what early data may do.

How applications protect themselves

  • Only allow safe, idempotent requests in early data, such as GET without side effects.
  • A server or CDN that forwards early data to a backend marks it with Early-Data: 1; the backend can answer 425 Too Early to make the client retry after the handshake (RFC 8470).
  • nginx has ssl_early_data off by default.

Traps

  • Saying TLS 1.3 handshakes are always 0-RTT. A first connection is 1-RTT; 0-RTT needs a prior ticket.
How did you do?Book 8.5 Example SystemsBook 8.4 Authentication Protocols