HTTPS and the TLS Handshake Explained

HTTPS = HTTP + TLS. The HTTP part is unchanged. TLS adds two things: encryption (so observers can’t read your traffic) and authentication (so you can verify you’re talking to the real example.com, not an impostor). The whole thing happens in a handshake before any HTTP data flows.

What TLS guarantees

  • Confidentiality — third parties can’t read what you send
  • Integrity — third parties can’t modify it without detection
  • Authentication — you’re talking to the real server (verified by certificate)

Note: it does NOT hide WHO you’re talking to. The destination IP and SNI hostname leak. (Encrypted ClientHello / ECH fixes this — newer.)

The TLS 1.3 handshake (1 round trip)

Client                                    Server
   |                                         |
   |  ClientHello                            |
   |  - supported versions, ciphers          |
   |  - key share (DH public key)            |
   |─────────────────────────────────────────→|
   |                                         |
   |     ServerHello + Cert + Finished       |
   |     - chosen cipher                     |
   |     - server's DH public key            |
   |     - server's certificate              |
   |     - signature proving cert ownership  |
   |←─────────────────────────────────────────|
   |                                         |
   |  Finished + first HTTP request (encrypted)|
   |─────────────────────────────────────────→|
   |                                         |
   |     HTTP response (encrypted)           |
   |←─────────────────────────────────────────|

1 RTT total. Compare to TLS 1.2 which needed 2 RTTs.

The 3 things happening at once

Inside that handshake, three independent jobs happen:

1. Cipher negotiation

Client lists ciphers it supports. Server picks the strongest both agree on. Modern: AES-GCM or ChaCha20-Poly1305 with SHA-256 or SHA-384.

2. Key exchange (Diffie-Hellman)

Both sides generate ephemeral key pairs. They exchange public keys and combine them with their private keys to compute the SAME shared secret — without ever transmitting the secret. This is the magic of Diffie-Hellman.

Because keys are ephemeral (regenerated each session), you get forward secrecy: even if the server’s long-term key is later compromised, past traffic stays private.

3. Server authentication

Server sends its X.509 certificate. The cert binds the server’s public key to its hostname (sudoflare.com), signed by a Certificate Authority (CA) that the client trusts. The server proves it owns the cert by signing the handshake with its private key.

The certificate chain

Your browser trusts (built-in trust store):
  Root CA (e.g. Let's Encrypt R3 root)
    ↓ signs
  Intermediate CA
    ↓ signs
  Server certificate (sudoflare.com)

Your browser walks up this chain to a root it already trusts. If any link is missing or expired, you get a certificate error.

Common cert errors and what they mean

  • NET::ERR_CERT_DATE_INVALID — cert expired. Renew it.
  • NET::ERR_CERT_AUTHORITY_INVALID — chain doesn’t lead to a trusted root. Self-signed or wrong issuer.
  • NET::ERR_CERT_COMMON_NAME_INVALID — cert is for a different hostname than what you visited.
  • NET::ERR_SSL_PROTOCOL_ERROR — server doesn’t support TLS or supports only ancient versions.

Get a certificate (free)

Use Let’s Encrypt via certbot:

# Install
sudo apt install certbot python3-certbot-nginx

# Get cert + auto-configure nginx
sudo certbot --nginx -d sudoflare.com -d www.sudoflare.com

# Auto-renews via systemd timer

Inspect a cert

# From the command line
openssl s_client -connect sudoflare.com:443 -servername sudoflare.com </dev/null 2>/dev/null 
  | openssl x509 -text

# Quick check of expiration
echo | openssl s_client -connect sudoflare.com:443 2>/dev/null | openssl x509 -noout -dates

What to learn next

HTTP/1.1 vs HTTP/2 vs HTTP/3 — what each version changed and why HTTP/3 abandoned TCP entirely. Up next.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *