SSL, TLS & HTTPS

intermediate ssl tls https encryption certificates

When we browse a site over plain HTTP, everything we send and receive — passwords, credit card numbers, personal data — travels in plain text. Anyone sitting on the same Wi-Fi, or any server between us and the destination, can read it all. That’s terrifying.

HTTPS fixes this by encrypting the traffic between our browser and the server. The “S” stands for Secure, and it uses a protocol called TLS (Transport Layer Security) to make it happen.

HTTP vs HTTPS

The difference is simple:

  • HTTP — Data travels in plain text. Anyone can intercept and read it.
  • HTTPS — Data is encrypted. Even if someone intercepts it, they see gibberish.

HTTPS also provides authentication (we know we’re talking to the real server, not an impersonator) and integrity (the data hasn’t been tampered with in transit).

SSL vs TLS — What’s the Difference?

SSL (Secure Sockets Layer) is the old protocol. It was replaced by TLS back in 1999. When people say “SSL certificate” today, they almost always mean a TLS certificate. SSL is technically dead — every version has known vulnerabilities. We use TLS 1.2 and TLS 1.3 in the real world.

But the name “SSL” stuck around in everyday language. “SSL certificate,” “SSL termination” — it all refers to TLS under the hood.

The TLS Handshake — Simplified

Before any encrypted data flows, the browser and server need to agree on how to encrypt. This negotiation is called the TLS handshake. Here’s the simplified version:

Browser (Client)
Server
1. Client Hello ──────→ "Here are the TLS versions and ciphers I support"
2. "Here's my certificate + chosen cipher" ←────── Server Hello + Cert
3. Verify Certificate browser checks with CA
4. Key Exchange ←────→ both derive shared secret key
5. Encrypted Connection Established ←═══→ all data is now encrypted

TLS 1.3 made this faster — it takes just 1 round-trip instead of 2. There’s even a “0-RTT” mode for repeat connections where the handshake is nearly instant.

Certificates and Certificate Authorities

A certificate is basically the server saying “I am who I claim to be.” But anyone can create a certificate and claim to be google.com. That’s where Certificate Authorities (CAs) come in.

A CA is a trusted third party that verifies domain ownership and signs certificates. Our browsers come pre-loaded with a list of trusted CAs. When the browser gets a certificate, it checks: “Was this signed by a CA I trust?” If yes, we get the padlock icon. If not, we get a scary warning page.

Let’s Encrypt

Before Let’s Encrypt, SSL certificates cost money and were a hassle to set up. Let’s Encrypt changed everything — it’s a free, automated CA. Tools like Certbot and Caddy can automatically obtain and renew certificates from Let’s Encrypt.

# Using Certbot to get a free certificate
sudo certbot --nginx -d example.com -d www.example.com

# Caddy does it automatically — just configure the domain
# Caddyfile:
# example.com {
#     reverse_proxy localhost:3000
# }
# That's it. Caddy handles TLS automatically.

Self-Signed Certificates in Development

In development, we sometimes need HTTPS but don’t want to deal with a real CA. We can create a self-signed certificate — one we sign ourselves.

# Generate a self-signed cert for local development
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -sha256 -days 365 -nodes \
  -subj "/CN=localhost"

# Use it with a Node.js server
# const https = require('https');
# const fs = require('fs');
# https.createServer({
#   key: fs.readFileSync('key.pem'),
#   cert: fs.readFileSync('cert.pem')
# }, app).listen(3000);

The browser will still show a warning because it doesn’t trust our homemade CA. We can either click through the warning or add the cert to our system’s trust store.

For local development, tools like mkcert make this much easier — they create a local CA and add it to the system trust store automatically.

Why Mixed Content Gets Blocked

If an HTTPS page loads a resource (image, script, stylesheet) over plain HTTP, the browser blocks it or shows a warning. This is called mixed content.

Why? Because that one insecure resource creates a hole in the encryption. An attacker could modify the HTTP resource in transit, injecting malicious code into an otherwise secure page. The browser protects us by refusing to load it.

https://example.com/page.html      ← secure
  └── loads http://cdn.com/app.js  ← BLOCKED (mixed content)
  └── loads https://cdn.com/app.js ← allowed

The fix is simple: make sure every resource on an HTTPS page is also loaded over HTTPS. Use //cdn.com/resource.js (protocol-relative) or just always use https://.

Encryption In Transit vs At Rest

TLS encrypts data in transit — while it’s moving between our browser and the server. Once the data arrives at the server, TLS’s job is done. The data sits on the server’s disk in whatever format the application stores it.

Encryption at rest is a separate concern — that’s about encrypting data on disk (using things like full-disk encryption, encrypted database columns, or encrypted S3 buckets). A secure system uses both.

In simple language, HTTPS wraps our HTTP traffic in a layer of encryption using TLS, so nobody between us and the server can read or tamper with the data.

References