This is the deep dive. Weâre going to walk through every message in the TLS 1.2 handshake, what it contains, and why itâs needed. By the end of this chapter, youâll understand exactly what happens in those milliseconds between typing a URL and seeing a page.
Think of the handshake like two people meeting for the first time at a business conference. In the first exchange, they introduce themselves and show their business cards. In the second exchange, they agree on a private code to use for the rest of the conversation. Only after both exchanges are complete can they start talking business.
The TLS 1.2 handshake requires two full round trips before encrypted data can flow. The following diagram shows every message in order:
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: Round Trip 1
C->>S: 1. ClientHello
S->>C: 2. ServerHello
S->>C: 3. Certificate
S->>C: 4. ServerKeyExchange
S->>C: 5. ServerHelloDone
Note over C,S: Round Trip 2
C->>S: 6. ClientKeyExchange
C->>S: 7. ChangeCipherSpec
C->>S: 8. Finished
S->>C: 9. ChangeCipherSpec
S->>C: 10. Finished
Note over C,S: Encrypted Application Data
C->>S: HTTP Request (encrypted)
S->>C: HTTP Response (encrypted)
The client initiates the handshake. The ClientHello contains:
The ClientHello is sent in plain text. An eavesdropper can see everything in it, including the SNI (which reveals which website youâre connecting to).
The server responds with its choices:
The server sends its certificate chain: the server certificate plus any intermediate CA certificates. The client needs these to verify the serverâs identity.
This message is only sent for cipher suites that use Diffie-Hellman key exchange (DHE or ECDHE). It contains:
The signature is critical. Without it, an attacker could substitute their own DH parameters and perform a man-in-the-middle attack. The signature proves the DH parameters came from the legitimate server.
For RSA key exchange (no DH), this message is not sent. The client encrypts the pre-master secret directly with the serverâs RSA public key.
A simple message that says âIâm done sending my hello messages.â The client now has everything it needs to proceed.
Before responding, the client validates the certificate chain: signature verification, validity period, domain match, revocation check, and trust chain. If any check fails, the handshake is aborted.
The clientâs contribution to the key exchange:
Both sides now have the pre-master secret (either computed via DH or exchanged via RSA). They combine it with the Client Random and Server Random to derive the master secret using the PRF:
master_secret = PRF(pre_master_secret, "master secret",
ClientHello.random + ServerHello.random)
From the master secret, they derive all the session keys: client write key, server write key, client write IV, server write IV, and MAC keys.
Both sides send this message to signal: âFrom now on, everything I send will be encrypted with the keys we just derived.â Itâs a single byte (0x01) in its own record.
The first encrypted message. It contains a hash of all handshake messages exchanged so far, encrypted with the new session keys. Both sides compute this hash independently.
If the hashes match, it proves:
If an attacker modified any handshake message (like removing strong cipher suites from the ClientHello), the hashes wonât match, and the handshake fails.
After both Finished messages are verified, the handshake is complete. All subsequent data is encrypted with AES (or whatever bulk cipher was negotiated) using the session keys.