TLS-SSL Handshake
TLS-SSL Handshake
Definition: The TLS (formerly SSL) handshake is the cryptographic negotiation two endpoints perform, before any application data is exchanged, to agree on protocol version, authenticate the server (and optionally the client), and derive a shared symmetric session key.
How It Works
TLS 1.2 handshake (the still-widely-deployed baseline):
- ClientHello: client sends supported TLS versions, cipher suites, a random nonce, and (via SNI) the hostname it’s connecting to.
- ServerHello: server picks a TLS version and cipher suite from the client’s list, sends its own random nonce.
- Certificate: server sends its X.509 certificate (and chain), proving its identity, signed by a Certificate Authority the client trusts.
- ServerKeyExchange / Key exchange: parameters for deriving the shared secret (e.g. Diffie-Hellman parameters for forward secrecy, or an RSA-encrypted pre-master secret).
- ServerHelloDone, then the client sends its own key exchange material, and both sides independently compute the same master secret from the exchanged randoms and key material.
- ChangeCipherSpec + Finished from both sides: each confirms it can now encrypt/decrypt correctly, and all subsequent records are encrypted with symmetric keys (typically AES-GCM or ChaCha20-Poly1305).
This takes 2 round trips before application data flows (1 for TCP’s handshake, plus roughly 2 more for TLS, though pipelining reduces the practical cost somewhat).
Under the Hood
TLS 1.3 (RFC 8446, 2018) is a significant redesign, not just a version bump:
- 1-RTT handshake by default: the client sends its key share (guessing the server’s preferred group) in the ClientHello itself, so the server can respond with ServerHello + Certificate + Finished in one flight, cutting the handshake to a single round trip.
- 0-RTT resumption: for a server the client has connected to before, it can send encrypted application data in its very first flight, using a pre-shared key (PSK) from a prior session, at the cost of losing forward secrecy and replay protection for that first batch of data (why 0-RTT is restricted to idempotent requests).
- Removed weak/legacy mechanisms entirely: static RSA key exchange (no forward secrecy), CBC-mode ciphers vulnerable to padding oracle attacks (like BEAST/POODLE-adjacent issues), compression (CRIME attack vector), and renegotiation are all gone.
- All handshake messages after ServerHello are encrypted, including the certificate, reducing what a passive observer can see about the connection.
Certificate validation involves walking the chain from the server’s leaf certificate up to a root CA in the client’s trust store, checking signatures at each link, validity dates, revocation status (via OCSP or CRLs), and that the certificate’s Subject Alternative Name matches the requested hostname (via SNI). Any break in that chain, an expired cert, a hostname mismatch, an untrusted root, produces the familiar browser warning.
Session resumption avoids a full handshake on reconnect: TLS 1.2 uses session IDs or session tickets; TLS 1.3 uses PSKs derived from a previous session, enabling that 0-RTT path. Forward secrecy (ensured by ephemeral Diffie-Hellman key exchange, mandatory in TLS 1.3) means that even if a server’s long-term private key is later compromised, past recorded sessions can’t be decrypted retroactively, since the actual session keys were never derived from that long-term key alone.
Certificate Chain Validation
When a client receives a server’s certificate, it doesn’t trust it in isolation, it validates a full chain:
- Leaf certificate: issued to the specific domain (
example.com), contains the public key the handshake will use. - Intermediate certificate(s): issued by a CA to another CA, forming a chain of delegated trust, most CAs don’t sign leaf certificates directly with their root key for security reasons.
- Root certificate: self-signed, pre-installed in the OS/browser’s trust store. The chain is valid only if it terminates at a root the client already trusts.
At each link, the client checks: the signature is valid, the certificate hasn’t expired, the certificate hasn’t been revoked (via OCSP stapling or a CRL), and, for the leaf, that the hostname matches a Subject Alternative Name entry. A missing intermediate certificate is a common real-world misconfiguration, browsers often cache intermediates from prior visits and paper over it, while a fresh client (like a mobile app or curl) fails outright.
Why It Matters
TLS is what makes it safe to send passwords, payment details, and private data over a network that’s fundamentally untrusted, any router or ISP between client and server. It provides confidentiality (encryption), integrity (tampering is detectable), and authenticity (you’re actually talking to the server you think you are, not an attacker intercepting the connection).
Version History
| Version | Year | Status |
|---|---|---|
| SSL 2.0 / 3.0 | 1995 / 1996 | Deprecated, broken (DROWN, POODLE) |
| TLS 1.0 / 1.1 | 1999 / 2006 | Deprecated by major browsers as of 2020 |
| TLS 1.2 | 2008 | Still widely used, secure with modern cipher suites |
| TLS 1.3 | 2018 | Current standard, faster and simpler |
The “SSL” name persists in casual usage (SSL certificate, SSL termination) purely out of habit, actual SSL versions have been considered insecure and unsupported by modern browsers for years.
Common Pitfalls
- Expired or misconfigured certificates breaking connectivity in production, browsers block with a hard warning, but API clients and mobile apps often fail with a much less obvious error, or worse, some are configured to silently ignore TLS errors, defeating the entire point.
- Confusing “encrypted” with “trustworthy”: a self-signed certificate encrypts the connection just as well as a CA-signed one, but provides no identity verification, an attacker can just as easily present their own self-signed cert.
- Disabling certificate validation to “fix” a dev-environment TLS error, then shipping that code to production.
- Not renewing certificates before expiry, especially with short-lived certs (Let’s Encrypt’s default 90 days) where automated renewal is assumed but silently fails.
- Assuming “SSL” and “TLS” are different technologies rather than the same lineage, SSL 2.0/3.0 are deprecated and insecure; “SSL certificate” in casual use almost always means a TLS certificate today.
- Missing SNI support on older clients/servers, causing the wrong certificate to be served when multiple HTTPS sites share one IP.
Comparison
| SSL 3.0 | TLS 1.2 | TLS 1.3 | |
|---|---|---|---|
| Status | Deprecated, insecure (POODLE) | Widely deployed, secure if configured well | Current standard |
| Handshake RTTs | 2 | 2 | 1 (0 with resumption) |
| Forward secrecy | Not guaranteed | Optional (cipher-suite dependent) | Mandatory |
| Weak ciphers (RC4, static RSA, CBC issues) | Allowed | Allowed unless disabled | Removed entirely |
| Handshake confidentiality | Mostly plaintext | Mostly plaintext | Encrypted after ServerHello |
| Cipher suite negotiation | Combined (e.g. TLS_RSA_WITH_AES_128_CBC_SHA) | Combined | Split, AEAD cipher separate from key exchange group |
| Renegotiation | Allowed (had CVE-2009-3555 vulnerability) | Allowed, patched | Removed entirely |
TLS vs mTLS
| TLS | mutual TLS (mTLS) | |
|---|---|---|
| Who presents a certificate | Server only | Both client and server |
| Typical use | Public websites, APIs | Service-to-service auth, zero-trust internal networks |
| Client identity | Not cryptographically verified | Verified via client certificate |
| Extra handshake step | None | Server requests and validates a client certificate |
Debugging Workflow: Reading openssl s_client Output
openssl s_client -connect example.com:443 -servername example.com
gives a direct view into exactly where a handshake fails:
CONNECTED(00000003)confirms the underlying TCP connection succeeded, if this line never appears, the problem is network/firewall-level, not TLS at all.- The certificate chain block lists each certificate in the chain with its subject and issuer. A chain that terminates without reaching a trusted root, or skips an intermediate, shows up here as a shorter-than-expected chain or a
Verify return codeother than0 (ok). Verify return codeis the single most useful line:18means self-signed certificate,10means expired,20/21mean the issuer chain couldn’t be verified, translating these numeric codes directly to the actual misconfiguration.New, TLSv1.3, Cipher is ...confirms the negotiated protocol version and cipher suite, useful when a client reports “handshake failure” and you need to know whether the server even offered a version/cipher combination the client supports.- Forcing a specific version, e.g.
-tls1_2or-tls1_3, isolates whether a failure is version-specific (common when a server has disabled older/newer protocols, or a legacy client can’t speak TLS 1.3 at all).
Example
openssl s_client -connect example.com:443 -tls1_3
shows the live handshake: negotiated protocol version, cipher suite, and the full certificate chain. curl -v https://example.com prints a condensed version of the same handshake steps. Browser DevTools’ Security tab shows the negotiated TLS version and cipher for the current page’s connection.
FAQ
Does TLS hide which website I’m visiting from my ISP? Mostly, but not entirely. The domain name in classic SNI is sent in plaintext during the ClientHello, so a network observer can see it even though the page content is encrypted, unless Encrypted Client Hello (ECH) is negotiated, which is still rolling out.
What happens if the client and server can’t agree on a cipher suite or version? The handshake fails outright with a fatal alert, no fallback to plaintext, which is by design, a silent downgrade to unencrypted would defeat the purpose.
Is TLS 1.3 always faster than TLS 1.2? For a fresh connection, yes, one fewer round trip. For a resumed session, TLS 1.2 session tickets and TLS 1.3 PSK resumption are both fast, the gap narrows.
Why do some sites still show a padlock even with an expired-looking cert warning bypassed? Because the browser padlock only reflects that a certificate was presented and the connection is encrypted at that moment, users clicking through a warning have told the browser to trust it anyway, the padlock doesn’t retroactively mean the identity check passed.
Related Terms
Referenced by