← Module 06 · Security & Encryption

TLS/SSL Handshake (1.2 vs 1.3)

How a client and server authenticate and derive traffic keys without sending those keys across the network. Modern connections use TLS; SSL is an obsolete predecessor.

Short answer: A certificate-authenticated TLS handshake negotiates parameters, proves the server's identity, and derives encryption keys. A typical full TLS 1.2 exchange takes two round trips; TLS 1.3 commonly takes one. Those counts exclude TCP setup and have resumption and retry exceptions.

Before this: symmetric and asymmetric encryption and certificate chains.

What the handshake has to accomplish

Meeting a new business contact for the first time means checking their credentials, agreeing on which shared rules you'll both follow, and settling on a private code only the two of you know before discussing anything sensitive. TLS (Transport Layer Security) does exactly that, in three jobs: agree on a protocol version and cipher suite, authenticate the server using the certificate chain from PKI & Digital Certificates, and establish shared symmetric session keys. That last part is hybrid encryption in action: asymmetric crypto is used only to set the session keys up, then fast symmetric encryption handles the actual data for the rest of the connection.

TLS 1.2: Two round trips

The ordinary full TLS 1.2 handshake shown here uses ephemeral elliptic-curve Diffie-Hellman (ECDHE) with server certificate authentication and no client certificate. It takes two round trips before the client can send application data after verifying the server's Finished. Resumption and the optional False Start optimization change this timing. In the business meeting analogy, the first exchange checks credentials and rules; the second confirms both parties derived the private code.

TLS 1.2: TWO ROUND TRIPS CLIENT SERVER ClientHello supported TLS versions and cipher suites ServerHello, Certificate, KeyExchange chosen cipher suite, the server's certificate, key material ClientKeyExchange, Finished client's half of the key material, switches to encrypted Finished both sides confirmed, encrypted data can now flow
The illustrated full handshake takes two round trips before the client sends application data. TCP setup, resumption, and False Start are outside this diagram.

What's actually on the wire, message by message

The diagram above shows the shape of the conversation. Here's what's actually inside each flight; expand any of them.

ClientHello client → server, plaintext
Version3,3, the wire encoding for "TLS 1.2"
Client Random32 random bytes, generated fresh for this connection
Session IDEmpty on a fresh connection, or a previous session's ID to try to resume it
Cipher SuitesA list the client is willing to use, e.g. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, in preference order
Extensionsserver_name (SNI, Server Name Indication: which hostname it's asking for), supported_groups (which elliptic curves it can do Diffie-Hellman with), signature_algorithms, and others
ServerHello server → client, plaintext
Server RandomAnother fresh 32 random bytes
Session IDA new one, or confirmation that the client's proposed resumption was accepted
Cipher SuiteThe single suite the server picked from the client's list
Certificate, ServerKeyExchange, ServerHelloDone server → client, plaintext

Sent as one flight, back to back.

CertificateThe server's X.509 certificate chain (see PKI & Digital Certificates), carrying its long-term public key
ServerKeyExchangeThe server's ephemeral Diffie-Hellman public key for this connection, plus a signature over it made with the certificate's private key, proving the server actually holds that key
ServerHelloDoneAn empty message: "that's everything from me for now"
ClientKeyExchange, ChangeCipherSpec, Finished client → server
ClientKeyExchangeThe client's own ephemeral Diffie-Hellman public key, still plaintext. Both sides can now compute the same shared secret independently
ChangeCipherSpecA single byte, 0x01: "everything after this is encrypted with the keys we just derived"
FinishedThe first encrypted message: a 12-byte value proving the client derived the same keys and saw the same handshake so far
ServerChangeCipherSpec, Finished server → client
ChangeCipherSpecThe server's own switch-to-encrypted signal
FinishedThe server's own 12-byte proof. Once the client verifies it, application data can flow both directions
How the session keys actually get derived math, not wire bytes

Nothing sent so far is the actual encryption key. Both sides separately compute it from what was exchanged, and never transmit it.

1. Pre-Master SecretBoth sides combine their own private key with the other side's public key (Diffie-Hellman). Same math, same result on both ends, without either one ever sending the secret itself
2. Master SecretA 48-byte value produced by the TLS 1.2 pseudorandom function. Its hash depends on the cipher suite. With Extended Master Secret (RFC 7627), derivation binds to the handshake transcript rather than just the two randoms
3. Key expansionThe master secret produces directional key material appropriate to the cipher suite. AEAD suites such as AES-GCM do not use separate record MAC keys; their authentication is integrated

TLS 1.3: One round trip, sometimes zero

TLS 1.3 commonly includes the client's key_share in ClientHello. If the server accepts the offered group, the client can verify the server's first flight and send Finished plus application data after one round trip. A HelloRetryRequest adds a round trip when another key share is needed. The business contact arrives with a proposed key-agreement method instead of asking which one to prepare. Messages after ServerHello are encrypted with handshake keys, before application traffic keys take over.

TLS 1.3: ONE ROUND TRIP CLIENT SERVER ClientHello + a guessed key share no more waiting to be told which method to use ServerHello, Certificate, Finished key share, certificate, and confirmation combined Finished one round trip total, encrypted data can now flow
Half the round trips of TLS 1.2. Reconnecting to a server visited recently can drop to zero extra round trips (0-RTT) using a resumed session, though 0-RTT data carries its own replay-attack caveats.

What's actually on the wire, message by message

ClientHello client → server, plaintext
Cipher SuitesA much shorter list, every option now an AEAD (Authenticated Encryption with Associated Data) cipher, e.g. TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256
key_shareThe new part: the client's own ephemeral Diffie-Hellman public key, sent immediately, guessing which group the server will accept
supported_versionsExplicitly states TLS 1.3, since the version field itself still says 1.2 for compatibility with old middleboxes that choke on an unrecognized version
ServerHello server → client, plaintext, the last unencrypted message
key_shareThe server's own ephemeral public key for the group it picked. The moment both sides have this, they can both compute the handshake keys
Cipher SuiteThe one chosen suite
EncryptedExtensions, Certificate, CertificateVerify, Finished server → client, encrypted

These TLS 1.3 server messages use handshake keys derived after ServerHello. They are not a one-for-one rearrangement of TLS 1.2 messages. In particular, EncryptedExtensions and server CertificateVerify have distinct TLS 1.3 roles.

EncryptedExtensionsExtensions that don't need to be public, now that encryption is already active
CertificateThe server's certificate chain, same as before, just now encrypted
CertificateVerifyA signature over a context-bound handshake transcript hash, proving possession of the certificate's private key. TLS 1.2 ECDHE also proves possession, through its signed ServerKeyExchange, but signs different material
FinishedProof the server derived the right keys, the same role it played in TLS 1.2
Finished client → server, encrypted

The client's proof authenticates its view of the transcript and confirms the handshake keys. Application traffic uses separate keys. The server can send application data after its own Finished, before receiving the client's Finished; it must not treat the client as authenticated before verification where client authentication is required.

0-RTT early data optional, requires a suitable PSK

With a suitable PSK (Pre-Shared Key), commonly from a previous session ticket, the client may send early application-data records alongside ClientHello, not inside that handshake message. The server may reject early data. It lacks forward secrecy and can be replayed, so application-level replay safety matters. A method named GET is not by itself proof that replay is harmless. The handshake still completes; 0-RTT describes when eligible early data can be sent.

PropertyTLS 1.2TLS 1.3
Typical full handshake, excluding TCPTwo RTTsOne RTT without HelloRetryRequest; optional 0-RTT early data has separate rules
Cipher selectionBroader suite set; current security guidance excludes weak choicesAEAD suites only; static RSA key transport and CBC suites removed
Forward secrecyDepends on key exchange, such as ECDHEProvided by ephemeral (EC)DHE; PSK-only mode and 0-RTT do not provide it

Worked example: negotiation is not identity

In an illustrative TLS 1.3 connection to portal.example, the client offers supported_versions = 0x0304 and an X25519 key_share. The server selects TLS_AES_128_GCM_SHA256 and returns its key share. This cipher-suite name selects record encryption and the key-schedule hash; it does not select X25519 or the certificate signature algorithm.

The client still has to validate a trusted certificate chain, check certificate validity, match the requested DNS name against the certificate's subjectAltName, and verify CertificateVerify and Finished. Agreeing on a private code with the business contact does not establish their identity until the credentials are checked. A passive TLS 1.3 capture can show the hellos but cannot normally read the encrypted certificate flight without session secrets.

FailureCheckInterpretation
Hostname mismatchCompare requested hostname, SNI, and certificate subjectAltNameReaching a server and negotiating encryption do not prove it is the intended server.
Unknown issuer or incomplete chainInspect the presented intermediates and the client's trust storeA locally trusted root may be absent on another device. Disabling verification hides the problem.
Protocol or handshake failureInspect client/server logs and supported versions, groups, and signature algorithmsA generic alert is not enough to identify which negotiation or policy check failed.
Expired or not-yet-valid certificateCheck certificate dates and the client's clockClock error and actual expiry can produce similar symptoms.
WHY THIS SITS ON TOP OF TCP, NOT INSTEAD OF IT

TLS still assumes a reliable, ordered byte stream underneath it, which is exactly what TCP provides. That's true for TLS 1.2 and 1.3 alike. QUIC, the transport HTTP/3 uses (see HTTP/HTTPS: 1.1 vs 2 vs 3), handles this differently by folding TLS 1.3 directly into its own transport instead of layering it on top of TCP.

Connect this to TCP connection setup and HTTP/2 and HTTP/3.