Updated April 2026
TLS Handshake Explained — How HTTPS Connections Are Established
Quick Answer
The TLS handshake authenticates the server and establishes a shared encryption key. TLS 1.3 does this in 1 round trip (1-RTT) vs TLS 1.2's 2 round trips (2-RTT). The handshake verifies the server certificate, negotiates a cipher suite, and derives session keys — all before any application data is sent.
Every HTTPS connection starts with a TLS handshake. It is invisible but adds latency and can fail in subtle ways — wrong certificate chain, unsupported cipher, expired cert. Understanding it helps you debug SSL errors and configure servers correctly.
Visualize your SSL chain →TLS 1.3 handshake (modern — 1-RTT)
Client Server | | |--- ClientHello -------------->| Supported ciphers, TLS version, key share | | |<-- ServerHello ______________| Chosen cipher, key share |<-- Certificate _______________| Server's cert chain |<-- CertificateVerify ________| Proof server owns the private key |<-- Finished __________________| Handshake MAC | | |--- Finished ----------------->| Client confirms handshake | | |=== Encrypted application data ===| HTTP request/response
TLS 1.3 completes in 1 round trip. Key exchange and cipher negotiation happen simultaneously in the first message.
TLS 1.2 handshake (legacy — 2-RTT)
Client Server |--- ClientHello -------------->| Supported ciphers, random |<-- ServerHello ---------------| Chosen cipher, random |<-- Certificate ---------------| Server cert |<-- ServerHelloDone -----------| | | |--- ClientKeyExchange -------->| Encrypted pre-master secret |--- ChangeCipherSpec --------->| |--- Finished ----------------->| | | |<-- ChangeCipherSpec -----------| |<-- Finished ------------------| | | |=== Encrypted application data ===|
Certificate verification — what the browser checks
1. Is the certificate for this domain? (Common Name or Subject Alternative Name matches) 2. Is the certificate expired? (Not Before <= today <= Not After) 3. Is the certificate signed by a trusted CA? (Chain: Leaf → Intermediate → Root in browser trust store) 4. Has the certificate been revoked? (OCSP check or CRL) 5. Does the server prove it owns the private key? (CertificateVerify signature in TLS 1.3)
What causes handshake failures
| Error | Cause | Fix |
|---|---|---|
| SSL_ERROR_BAD_CERT_DOMAIN | Certificate doesn't match domain | Reissue cert for correct domain |
| CERT_HAS_EXPIRED | Certificate past Not After date | Renew certificate |
| UNABLE_TO_VERIFY_LEAF_SIGNATURE | Missing intermediate certificate | Use fullchain.pem in Nginx |
| SSL_ERROR_NO_CYPHER_OVERLAP | No common cipher suite | Enable TLS 1.2+ and ECDHE ciphers |
| HANDSHAKE_FAILURE | TLS version mismatch | Enable TLS 1.2 minimum |
Debug a TLS handshake
# Full handshake details openssl s_client -connect example.com:443 -showcerts </dev/null 2>&1 # Check TLS version negotiated openssl s_client -connect example.com:443 </dev/null 2>&1 | grep "New," # Test specific TLS version openssl s_client -connect example.com:443 -tls1_2 </dev/null openssl s_client -connect example.com:443 -tls1_3 </dev/nullCheck your SSL chain and cipher suite →