skip to content

In a TLS 1.3 handshake, from which message onward can a passive on-path observer no longer read the handshake?

level: middleimportance: should knowfreq 48%

answer

  1. keys cannot protect their own creation
  2. two hello messages travel in the clear
  3. protection starts as early as possible
  4. the first protected message is EncryptedExtensions
  5. in 1.2 only Finished was protected

basics

~10 s

From EncryptedExtensions. In TLS 1.3 only the two hello messages travel in the clear; every handshake message after ServerHello is protected under the handshake traffic keys, which is exactly why the EncryptedExtensions message exists.

solid answer

~40 s

`ClientHello` and `ServerHello` must be readable, because they are what let the two sides derive keys in the first place. The moment those keys exist, protection begins: `EncryptedExtensions` is the first protected handshake message, and everything after it — the certificate, the transcript signature, both `Finished` messages — is protected too. `EncryptedExtensions` exists precisely because there was suddenly somewhere better to put extension answers than the cleartext `ServerHello`. The practical consequence is that the host name a client offers is still visible on the path, while the server's answers, including which application protocol was chosen, are not. In TLS 1.2 none of this held: every handshake message was in the clear except each side's `Finished`.

code

pseudocode · 18 lines
pseudocode
TLS 1.3 handshake, by visibility

  readable on the path:
    ClientHello        <- the offered host name is here
    ServerHello

  protected under the handshake traffic keys:
    EncryptedExtensions   <- first message an observer cannot read
    Certificate
    CertificateVerify
    Finished              (both directions)

TLS 1.2 handshake, by visibility

  readable on the path:
    everything up to and including ChangeCipherSpec
  protected:
    Finished              (each side, after its ChangeCipherSpec)

go deeper

for a junior

Know that the two hello messages are readable on the path and that protection starts right after them in TLS 1.3. The name of the first protected message, EncryptedExtensions, is worth remembering.

for a middle

Explain why the boundary sits where it does: keys cannot protect the messages that create them. Then say what moved as a result, particularly the server's extension answers and the certificate, and contrast it with TLS 1.2.

for a senior

Anticipate the operational fallout. Captures carry less evidence after an upgrade, and any intermediary that made decisions on the server's answers has lost its input. Say where the evidence went instead.

for a principal

Treat handshake visibility as an observability and dependency question for the estate: which systems were quietly reading the server's half of the handshake, and what they need to be given now that it is protected.

## Where the curtain falls A handshake cannot be protected from its own first byte: the keys that would protect it do not exist yet. So TLS 1.3 protects everything from the earliest moment it can, which is immediately after the two hello messages have supplied enough material to derive the handshake traffic keys. - **`ClientHello`** — in the clear. It has to be: the server has no keys for this connection yet. - **`ServerHello`** — in the clear, for the same reason in the other direction. - **`EncryptedExtensions`** — the **first protected handshake message**, and always present in a full handshake even when it has little to say. - **`Certificate`**, the transcript signature, **`Finished`** — all protected. ## Why EncryptedExtensions exists at all In TLS 1.2 the server's answers to the client's extensions had nowhere to go but the `ServerHello`, which is sent before any keys exist and is therefore readable by anyone. TLS 1.3 splits the server's extension answers in two: 1. Extensions **needed to establish the cryptographic context** stay in `ServerHello`, because without them the other side cannot derive keys and nothing later could be read. 2. **Everything else** moves into `EncryptedExtensions`, which is the first message the new keys cover. That split is the entire reason the message exists, and it is why the answer to "where does the server tell me which application protocol it picked?" is different in 1.3 from 1.2. ## What an observer still sees, and what it does not | Item | TLS 1.2 | TLS 1.3 | |---|---|---| | Host name offered by the client | visible | visible | | Cipher suites offered | visible | visible | | Selected cipher suite | visible | visible | | Server's extension answers | visible | protected | | Selected application protocol | visible | protected | | Server certificate | visible | protected | | Each side's `Finished` | protected | protected | The row that surprises people is the certificate. In a 1.2 capture you can read the server's certificate straight off the wire; in a 1.3 capture you cannot, because it arrives after `EncryptedExtensions`. ## What this changes in practice For a ticketing gateway, three consequences follow directly: - **Anything on the path can still tell which name a client asked for**, because that offer is in the cleartext `ClientHello`. Moving the visible boundary earlier than that is a different mechanism entirely, and not part of the ordinary handshake. - **Diagnosis from a capture gets thinner.** Before, a trace showed the certificate the gateway served and the protocol it selected. After, the trace shows two hello messages and then opaque records, so a failure inside the server's flight looks the same as any other failure inside the server's flight. - **Intermediaries that used to make decisions on the server's answers cannot.** Anything that read the selected protocol, or inspected the served certificate, is reading material that is no longer on the wire. ## The TLS 1.2 picture, stated precisely It is tempting to say TLS 1.2 handshakes are unencrypted, and that is nearly right but too strong. Record protection in 1.2 starts after a side sends its `ChangeCipherSpec` record, and the very next message it sends is `Finished`. So each side's `Finished` **is** protected, and everything before it is not. That detail matters when reading an old capture: the point where the messages stop being parseable is the `ChangeCipherSpec`, not the end of the handshake. ## Version note This is one of the sharpest behavioural differences between the two versions, and it is worth stating the version whenever the question of visibility comes up. "The certificate is visible on the wire" is true of TLS 1.2 and false of TLS 1.3, and an answer that omits the version is half wrong either way.

  • Why can EncryptedExtensions not simply be merged into the ServerHello?
    Because `ServerHello` is sent before protection exists and must stay readable — it carries what the peer needs in order to derive keys at all. Merging the two would put every extension answer back in the clear, which is the situation TLS 1.3 was changing. The split is what allows the answers to be protected while the key-establishment material stays visible.
  • A gateway is upgraded from TLS 1.2 to 1.3 and a team reports that their packet captures suddenly show less. What changed?
    Everything after `ServerHello` is now protected, so the served certificate and the server's extension answers are no longer in the capture. Nothing is broken; the evidence moved. Diagnosis has to come from what each endpoint logs about its own handshake outcome rather than from reading the exchange off the wire.

saying these in an interview costs you the question

  • Says the whole TLS 1.3 handshake is encrypted end to end
  • Claims the offered host name is hidden in ordinary TLS 1.3
  • Thinks certificates are protected on the wire in TLS 1.2
  • Believes no part of a TLS 1.2 handshake is ever protected
  • Assumes EncryptedExtensions exists in both versions