How HTTPS and TLS Really Work: A Practical Guide
Why HTTPS Matters (and Why You Should Understand It)
You've probably seen the padlock icon in your browser and know that HTTPS encrypts traffic. But when a certificate error appears, or an API call fails with a TLS error, do you know exactly what's happening? Many developers treat HTTPS as a black box—until something breaks. This guide unpacks how HTTPS and TLS actually work, from the handshake to the certificate chain, so you can debug issues with confidence.
The Basics: HTTPS = HTTP + TLS
HTTPS is simply HTTP layered on top of TLS (Transport Layer Security). TLS provides three guarantees:
- Encryption: Data is scrambled so eavesdroppers can't read it.
- Authentication: You're talking to the real server, not an impostor.
- Integrity: Data can't be modified in transit without detection.
Before TLS 1.3, the protocol was called SSL (Secure Sockets Layer), but SSL is deprecated. Today, TLS 1.2 and 1.3 are the standards.
The TLS Handshake: Step by Step
The handshake is where the magic happens. It's a conversation that establishes a secure channel before any HTTP data is sent. Here's a simplified version for TLS 1.2 (TLS 1.3 is faster but similar in concept):
- Client Hello: The client sends supported TLS versions, cipher suites, and a random value (Client Random).
- Server Hello: The server picks a TLS version and cipher suite, sends its own random value (Server Random), and presents its certificate.
- Certificate Verification: The client checks the certificate against trusted root CAs, expiration, and domain name.
- Key Exchange: Using algorithms like ECDHE, both parties derive a shared secret (pre-master secret) without ever sending it over the wire.
- Finished: Both sides verify the handshake integrity and switch to encrypted communication using symmetric keys derived from the shared secret.
In TLS 1.3, the handshake is reduced to one round trip (1-RTT) and even supports 0-RTT for resumed sessions, improving latency.
Why asymmetric encryption is only used initially
Asymmetric cryptography (like RSA or ECDSA) is slow and computationally expensive. TLS uses it only to securely exchange a symmetric session key, which is then used for bulk encryption (e.g., AES-GCM or ChaCha20-Poly1305). This hybrid approach balances security and performance.
Certificates and the Chain of Trust
A certificate binds a public key to a domain name and is signed by a Certificate Authority (CA). Browsers and operating systems ship with a store of trusted root CAs. When a server presents its certificate, the client builds a chain from the server certificate to an intermediate CA and finally to a trusted root.
Common certificate errors include:
- Expired certificate: The certificate's validity period has ended.
- Hostname mismatch: The certificate's Subject Alternative Name (SAN) doesn't match the requested domain.
- Untrusted issuer: The root CA isn't in the client's trust store (e.g., self-signed certificates).
- Incomplete chain: The server didn't send intermediate certificates, so the client can't build a path to a trusted root.
Tools like openssl s_client or online SSL checkers help diagnose these issues.
Debugging HTTPS Connections
When HTTPS fails, you need to inspect the handshake. Here are practical commands:
# Check certificate details and chain
openssl s_client -connect example.com:443 -servername example.com -showcerts
# Verify TLS version and cipher
openssl s_client -connect example.com:443 -tls1_3
# Test certificate expiration
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
In browsers, the Developer Tools Security panel shows connection details, and curl -v https://example.com reveals handshake steps.
Common TLS Misconfigurations
Even with HTTPS enabled, misconfigurations can weaken security or break compatibility:
| Issue | Impact | Fix |
|---|---|---|
| Weak cipher suites enabled | Susceptible to downgrade attacks | Disable RC4, DES, and export ciphers; prefer AEAD ciphers |
| Missing HSTS header | Vulnerable to SSL stripping | Add Strict-Transport-Security header |
| Incomplete certificate chain | Errors on some clients | Include intermediate certificates in server config |
| Old TLS versions allowed (1.0/1.1) | Compliance and security risks | Disable TLS 1.0 and 1.1; enforce TLS 1.2+ |
How to Inspect TLS in Practice
If you're debugging a web server, start by checking the certificate chain and cipher suite. For Nginx, ensure your configuration includes the full chain:
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
Use online tools like SSL Labs for a comprehensive report, but always verify with command-line tools for quick checks.
FAQ
What is the difference between TLS and SSL?
SSL is the predecessor of TLS. SSL versions 2.0 and 3.0 are deprecated due to security vulnerabilities. TLS 1.2 and 1.3 are the current secure protocols.
Why does my browser show a certificate warning even though the certificate is valid?
Common causes include an incomplete certificate chain, a hostname mismatch, or the certificate being issued by a CA not trusted by your system. Check the certificate's SAN and ensure intermediates are served.
How can I check which TLS version my server supports?
Use openssl s_client -connect yourdomain.com:443 -tls1_3 (or -tls1_2) and look for the protocol in the output. Online tools like SSL Labs also provide detailed reports.
When you need to quickly inspect or format JSON data from API responses during debugging, the JSON Formatter can help you visualize and validate the structure.