HTTPS and TLS: What Happens During the Handshake
When you visit a site over HTTPS, your browser and the server exchange a series of messages before a single byte of your actual request is sent. This exchange - the TLS handshake - establishes the encrypted channel that protects everything that follows.
Most engineers know HTTPS means “encrypted.” Fewer know what’s actually being negotiated, why, and what can go wrong. That matters when you’re debugging a certificate error, configuring a load balancer, or thinking about what “secure” actually means in your system.
What TLS provides
TLS (Transport Layer Security) sits between TCP and HTTP. It provides three things:
Confidentiality - the data transmitted is encrypted. Someone intercepting the packets between you and the server sees ciphertext, not the contents of your request or response.
Integrity - the data cannot be modified in transit without detection. Each record includes a MAC (message authentication code) that verifies the data hasn’t been altered.
Authentication - you can verify that the server you’re talking to is who it claims to be. This is what certificates do. Without authentication, encryption alone doesn’t help - you might be encrypting your data for an attacker.
HTTP alone provides none of these.
Certificates and the chain of trust
Before the handshake, the server needs a certificate - a digital document that says “this public key belongs to this domain.” The certificate is issued by a Certificate Authority (CA): a trusted organization whose root certificates are embedded in your operating system and browser.
The chain works like this: your OS ships with a set of trusted root certificates (e.g., DigiCert, Let’s Encrypt, Comodo). A CA uses its root to sign intermediate certificates. Those intermediates sign the certificate for your domain. When your browser sees a certificate, it walks this chain back to a trusted root. If it can’t, it rejects the connection.
Let’s Encrypt changed this landscape significantly. Free, automated, 90-day certificates made HTTPS viable for everyone. The automation (ACME protocol) handles renewal without manual intervention, which removed the main operational reason for not using HTTPS.
A certificate contains: the domain name(s) it’s valid for, the public key, the issuer, validity period, and the CA’s signature. Wildcard certificates cover *.example.com - one cert for all subdomains. SAN (Subject Alternative Name) certificates cover multiple specific domains in one cert.
The TLS handshake (TLS 1.3)
TLS 1.3, standardized in 2018 and now the dominant version, completes the handshake in one round trip. Here’s what happens:
1. ClientHello
The client sends: the TLS version it supports, a random value (client random), the cipher suites it supports (algorithm combinations for key exchange, encryption, and MAC), and optionally a key share - the client’s contribution to key exchange, computed in advance.
2. ServerHello + Certificate + Finished
The server responds in a single flight: it selects a cipher suite from what the client offered, sends its own random value (server random), completes the key exchange with its own key share, sends its certificate, and sends a Finished message - already encrypted, because at this point both sides can derive the session keys.
3. Client Finished
The client verifies the certificate (is it valid? does it match the domain? does it chain to a trusted root?), derives the same session keys, and sends its own Finished message.
From this point, all HTTP traffic flows encrypted. The entire handshake is one round trip for a new connection, zero round trips if the client has a pre-shared session (0-RTT, with caveats around replay attacks).
How the keys work
The key exchange in TLS 1.3 uses Diffie-Hellman. The clever property of DH: both sides can independently derive the same shared secret without ever transmitting it. An observer watching the exchange sees the public components but cannot compute the secret.
From the client random, server random, and the DH shared secret, both sides derive identical session keys using a key derivation function (HKDF). These symmetric keys are then used for AES-GCM or ChaCha20-Poly1305 encryption - both fast, authenticated encryption schemes.
The asymmetric key in the certificate (RSA or ECDSA) is only used to authenticate the server - to prove it controls the private key corresponding to the public key in the cert. It’s not used for the bulk encryption. This separation is what gives TLS its forward secrecy property: even if the server’s private key is compromised later, past sessions cannot be decrypted because the session keys are derived from ephemeral DH values, not the long-term key.
TLS 1.2 vs 1.3
TLS 1.2, still widely deployed, requires two round trips for the handshake. It also supports weaker cipher suites - some of which have been broken (RC4, 3DES) and are disabled by modern clients and servers, but the option to negotiate them existed.
TLS 1.3 removed all the weak options. There’s no negotiation of broken ciphers because they’re simply not in the protocol. It also made forward secrecy mandatory - TLS 1.2 allowed RSA key exchange, which doesn’t have this property.
If you’re configuring a server today, TLSv1.3 with TLSv1.2 as a fallback for legacy clients is the standard recommendation. TLS 1.0 and 1.1 should be disabled.
What certificate errors actually mean
ERR_CERT_AUTHORITY_INVALID - the cert was issued by a CA the browser doesn’t trust. This happens with self-signed certificates in development, or when an intermediate CA cert is missing from the server’s response (a misconfigured chain).
ERR_CERT_COMMON_NAME_INVALID - the hostname in the request doesn’t match the names on the certificate. Visiting api.example.com with a cert for www.example.com produces this. Wildcard certs only cover one subdomain level - *.example.com covers api.example.com but not v1.api.example.com.
ERR_CERT_DATE_INVALID - the certificate has expired. With Let’s Encrypt’s 90-day certs, automated renewal is not optional - it’s the only practical approach. A broken renewal cron job is a common production incident.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH - the client and server can’t agree on a TLS version or cipher suite. Usually indicates a server that hasn’t been updated to support modern TLS, or a client constrained to a specific version.
What HTTPS doesn’t protect
HTTPS encrypts the body of your requests and responses. It does not encrypt the hostname - DNS queries reveal it, and the SNI (Server Name Indication) field in the ClientHello is visible to network observers (though TLS 1.3’s Encrypted Client Hello is addressing this). The IP address is always visible.
HTTPS also doesn’t protect against a compromised server. If the server is breached, the attacker can read the decrypted data. Encryption protects data in transit, not data at rest on the server.
And HTTPS doesn’t mean the site is legitimate. A phishing site can have a valid TLS certificate - the padlock just means the connection is encrypted, not that you should trust what’s on the other end. Certificate pinning, HSTS, and careful user education exist for exactly this reason.
The handshake is fast, the math is solid, and the tooling has matured. The gap between “I know HTTPS is good” and “I understand what it actually does” is smaller than most engineers expect - and it’s the gap that matters when something breaks.