Skip to content

TLS/SSL and HTTPS

HTTP sends everything in plaintext. Anyone between you and the server (ISP, a coffee shop router, a MITM attacker) can read or modify it. TLS (Transport Layer Security) wraps HTTP in an encrypted tunnel - the result is HTTPS.

Why TLS Exists

TLS operates at the session/presentation layer (between TCP and the application). It provides:

  • Confidentiality - traffic is encrypted, eavesdroppers can’t read it
  • Integrity - data can’t be tampered with undetected (HMAC)
  • Authentication - you’re talking to the real server, not an impersonator (certificates)

Before any encrypted data flows, the client and server negotiate which algorithms to use and exchange keys:

TLS Handshake Pre Encryption

Client Server
│ │
│──── ClientHello ─────────────────────────▶│
│ (TLS version, cipher suites, │
│ client random, SNI) │
│ │
│◀─── ServerHello ─────────────────────────│
│ (chosen cipher suite, │
│ server random, session ID) │
│ │
│◀─── Certificate ─────────────────────────│
│ (server's X.509 cert) │
│ │
│◀─── ServerHelloDone ─────────────────────│
│ │
│ [Client verifies certificate] │
│ │
│──── ClientKeyExchange ───────────────────▶│
│ (pre-master secret, encrypted │
│ with server's public key) │
│ │
│ [Both sides derive session keys │
│ from pre-master + both randoms] │
│ │
│──── ChangeCipherSpec ───────────────────▶│
│──── Finished (encrypted) ───────────────▶│
│◀─── ChangeCipherSpec ────────────────────│
│◀─── Finished (encrypted) ────────────────│
│ │
│═══════ Encrypted Application Data ════════│

Key insight: The pre-master secret is never transmitted directly. Both sides independently derive the same session key using the same inputs (pre-master secret + both random values). This is why intercepting the encrypted key exchange doesn’t give you the session key.


TLS 1.3 (2018) makes the handshake faster and removes weak algorithms:

AspectTLS 1.2TLS 1.3
Handshake round trips2 round trips1 round trip (0-RTT possible for repeat visits)
Key exchangeRSA or DHEOnly ECDHE (ephemeral, forward secrecy mandatory)
Cipher suites37 options (many weak)5 options (all strong)
Forward secrecyOptionalRequired
Replay attacksNot addressed0-RTT has limited replay protection
RemovedN/ARC4, DES, 3DES, MD5, SHA-1, RSA key exchange, static DH

TLS 1.3


A TLS certificate is an X.509 document that:

  • Contains the server’s public key
  • Is signed by a Certificate Authority (CA) that vouches for the server’s identity
  • Contains the domain name(s) it’s valid for (Subject Alternative Names)
  • Has an expiry date
Root CA (self-signed)
└── Intermediate CA (signed by Root CA)
└── Server Certificate (signed by Intermediate CA)
└── Your website's public key

Browsers ship with a list of trusted Root CAs (Certificate Store). When you visit HTTPS:

  1. Server sends its certificate + intermediate CA’s certificate
  2. Browser walks the chain: Server cert → Intermediate CA → Root CA
  3. If the chain terminates at a trusted Root CA and the domain matches → ✅ trusted

Certificate Fields

FieldExamplePurpose
Subject CNexample.comPrimary domain
Subject Alternative Names*.example.com, example.orgAll valid domains
IssuerDigiCert Inc.Who signed this cert
Valid From / To2024-01-01 → 2025-01-01Validity period
Public KeyRSA 2048 or EC P-256Encrypt to this key
Signature(binary)Issuer’s endorsement
Serial Number0x...Unique ID (used in revocation)

Terminal window
# Check a certificate directly from a server
openssl s_client -connect example.com:443 -servername example.com
# Show just the certificate details
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -text
# Check expiry date only
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -dates
# notBefore=Jan 1 00:00:00 2024 GMT
# notAfter=Jan 1 00:00:00 2025 GMT
# Check which TLS version and cipher is negotiated
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| grep -E "Protocol|Cipher"
# Protocol : TLSv1.3
# Cipher : TLS_AES_256_GCM_SHA384
# Read a local certificate file
openssl x509 -in certificate.crt -text -noout
# Check if cert and private key match (fingerprints must match)
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5
# Test specific TLS versions
openssl s_client -connect example.com:443 -tls1_2 # force TLS 1.2
openssl s_client -connect example.com:443 -tls1_3 # force TLS 1.3
# Decode what a server returns (for debugging APIs)
curl -v --cacert /etc/ssl/certs/ca-certificates.crt https://api.example.com/
# Skip certificate verification (ONLY for debugging, never production)
curl -k https://example.com

ErrorMeaningFix
SSL_ERROR_RX_RECORD_TOO_LONGConnecting to HTTP port with HTTPSCheck port (use 443 not 80)
certificate verify failedCert not trusted (bad CA, expired, wrong domain)Check cert chain and expiry
SSL handshake failedProtocol mismatch (TLS version incompatible)Check supported TLS versions
ERR_CERT_DATE_INVALIDCertificate expiredRenew certificate
ERR_CERT_COMMON_NAME_INVALIDDomain doesn’t match cert SANCheck cert’s Subject Alternative Names
NET::ERR_CERT_AUTHORITY_INVALIDSelf-signed / unknown CAAdd CA to trust store

A cipher suite is a combination of algorithms used for:

  1. Key exchange (how to establish the session key)
  2. Authentication (how to verify identity)
  3. Symmetric encryption (how to encrypt the data stream)
  4. Message authentication (how to verify integrity)

Cipher Suites

TLS 1.3 cipher suite example: TLS_AES_256_GCM_SHA384

  • AES_256_GCM → AES-256 in GCM mode (authenticated encryption)
  • SHA384 → HMAC for integrity

TLS 1.2 cipher suite example: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

  • ECDHE → Elliptic Curve Diffie-Hellman Ephemeral (key exchange, forward secrecy)
  • RSA → RSA for authenticating the server
  • AES_256_GCM → symmetric encryption
  • SHA384 → HMAC