All Posts

How SSL/TLS Works: The Handshake Explained

When you see the green lock icon, your data is safe. But how? We break down the SSL Handshake, Public/Private Keys, and Certificates.

Abstract AlgorithmsAbstract Algorithms
ยทยท15 min read

AI-assisted content.

TLDR: SSL (now TLS) secures data between your browser and a server. It uses Asymmetric Encryption (Public/Private keys) once โ€” to safely exchange a fast Symmetric Session Key. Everything after the handshake is encrypted with the session key.


๐Ÿ“– The Locked Box Trick: Why Two Encryption Systems?

Alice wants to send Bob a secret letter, but Eve is intercepting all mail.

  • Symmetric encryption: Same key locks and unlocks. Fast โ€” but how do Alice and Bob share the key without Eve intercepting it?
  • Asymmetric encryption: Bob publishes an Open Padlock (public key) and keeps the only Key (private key). Alice locks her letter with Bob's padlock. Eve sees the locked box but can't open it. Only Bob can.
TypeSpeedKey distribution problem?
Symmetric (AES)Very fastYes โ€” how to share the key safely?
Asymmetric (RSA/ECDH)SlowNo โ€” public key can be shared openly

TLS Strategy: Use asymmetric encryption once (during the handshake) to securely exchange a symmetric session key. Then use the fast session key for everything else.


๐Ÿ” Symmetric vs. Asymmetric: The Two Locks Every Browser Uses

Before TLS can protect anything, both sides need to agree on a secret โ€” without ever having met. That is the core challenge encryption solves, and TLS tackles it with two complementary approaches.

Symmetric encryption (AES) uses one shared key to both encrypt and decrypt. It is blazing fast โ€” modern CPUs have hardware-level AES acceleration, so it adds almost zero latency to data transfer. The catch: how do two strangers share that one key when an attacker might be eavesdropping on the wire?

Asymmetric encryption (RSA / ECDH) solves the key-sharing problem with a mathematically linked pair: a public key anyone can use to encrypt a message, and a private key only the owner can use to decrypt it. You can publish your public key on a billboard โ€” it is mathematically useless for decryption without the private key. The catch: asymmetric operations are 100โ€“1000ร— slower than symmetric ones.

PropertySymmetric (AES)Asymmetric (RSA/ECDH)
SpeedVery fast (hardware-accelerated)Slow (100โ€“1000ร— slower)
Key sharingRisky โ€” both sides must already have itSafe โ€” public key can be shared openly
Use in TLSEncrypts all data after the handshakeUsed once to negotiate the session key

TLS's elegant solution: use asymmetric encryption for exactly one job โ€” securely exchanging a symmetric session key โ€” then hand off all bulk data encryption to fast AES. You get the security of asymmetric without the speed penalty.


๐Ÿ”ข The TLS 1.3 Handshake: Step by Step

This happens in milliseconds every time you visit https://google.com.

sequenceDiagram
    participant B as Browser (Client)
    participant S as Server (google.com)

    B->>S: ClientHello (TLS version, cipher suites, random nonce)
    S->>B: ServerHello (chosen cipher, random nonce)
    S->>B: Certificate (server's public key, signed by CA)
    S->>B: Key Share (ECDH public value)
    Note over B: Verify certificate against trusted CAs
    B->>S: Key Share (browser's ECDH public value)
    Note over B,S: Both derive the same Session Key independently
    B->>S: Finished (encrypted with session key)
    S->>B: Finished (encrypted with session key)
    Note over B,S: Handshake complete  all further data encrypted

The handshake sequence reveals TLS 1.3's core insight: asymmetric and symmetric cryptography are used in strict sequence, never interchangeably. The browser and server exchange ECDH public values in the Key Share messages โ€” neither side ever transmits the session key directly; both independently derive the same shared secret from the ECDH mathematics, which is why a passive eavesdropper recording the exchange gains nothing. The Verify certificate note is the trust anchor of the entire protocol: if the server's certificate does not chain to a CA pre-installed in the OS trust store, the handshake aborts here before any key material is derived. TLS 1.3 completes this entire sequence in a single round trip, halving the latency overhead compared to TLS 1.2.

TLS 1.3 improvement over TLS 1.2:The handshake completes in 1 RTT (round trip) instead of 2. Resumed sessions can use 0-RTT for even lower latency.

What the Certificate Tells the Browser

The server certificate contains:

  1. Subject: CN=google.com โ€” who owns this key.
  2. Public Key: The server's asymmetric key.
  3. Issuer: CN=DigiCert Global CA โ€” who vouches for it.
  4. Validity Period: Not before / not after dates.
  5. Signature: The CA's digital signature over all of the above.

โš™๏ธ Certificates and the Chain of Trust

Your browser doesn't know every website. It knows a small set of Root CAs (DigiCert, Let's Encrypt, GlobalSign) pre-installed in your OS/browser trust store.

flowchart TD
    Root[Root CA (Self-Signed  in your OS trust store)]
    Intermediate[Intermediate CA (Signed by Root)]
    Leaf[Leaf Certificate google.com (Signed by Intermediate)]

    Root --> Intermediate --> Leaf

The three-node chain encodes a critical operational security decision: Root CA private keys are kept offline in air-gapped HSMs and never used for day-to-day certificate signing. The Intermediate CA handles routine leaf certificate issuance and can be revoked independently โ€” if an Intermediate is compromised, the Root issues a new CRL excluding it, and only that Intermediate's issued certificates are affected. This containment architecture means compromising a well-run Intermediate CA is a serious but bounded incident; if the Root CA private key were exposed, every certificate in its chain across the entire internet would need to be re-issued.

Validation chain: Browser checks Leaf โ†’ Intermediate โ†’ Root โ†’ Root is in trust store โ†’ Valid.

If any link in the chain is missing or expired, the browser shows the red "Not Secure" warning.

Why not sign leaf certs with the Root directly?
Root private keys are stored offline in HSMs. Exposing them for every leaf cert would be a catastrophic security risk. Intermediate CAs handle day-to-day signing; if an Intermediate is compromised, only it needs to be revoked.


๐Ÿ“Š The Full TLS Handshake as a Decision Flowchart

The sequence diagram above shows what messages are sent. This flowchart shows why the handshake can succeed or fail โ€” including the critical certificate validation branch that determines whether a secure channel opens or the browser shows a red warning.

flowchart TD
    A[1 Browser sends ClientHello TLS version + cipher suites + random nonce] --> B[2 Server sends ServerHello Chosen cipher + Certificate + ECDH key share]
    B --> C[3 Browser checks certificate chain Leaf  Intermediate  Root CA]
    C --> D{Root CA in trust store?}
    D -- "No / Expired" --> E[ Handshake aborted Browser shows 'Not Secure' warning]
    D -- "Yes" --> F[4 Browser sends its ECDH key share]
    F --> G[5 Both sides independently derive the same Session Key from ECDH values]
    G --> H[6 Both send Finished message encrypted with the new session key]
    H --> I[ Encrypted channel open All traffic protected with AES-GCM]

The decision branch at step 3 โ€” "Root CA in trust store?" โ€” is where the vast majority of real-world TLS errors originate: expired leaf certificates, incomplete chains where the server forgot to include the Intermediate CA cert, or self-signed certificates that were never added to the trust store. Steps 1 through 4 complete in a single network round trip in TLS 1.3: the browser sends its ECDH key share and the Finished message in the same flight, so the server can derive the session key and reply without waiting for another client transmission. Once both Finished messages are verified using the newly derived session key, the channel is cryptographically confirmed and all subsequent HTTP data flows under AES-GCM encryption with effectively zero additional latency cost.

Key insight from the diagram:Steps 1โ€“4 happen in a single round trip in TLS 1.3. The entire overhead is one network round trip plus the certificate validation check at step 3. That branch is where most real-world TLS errors originate โ€” expired certs, incomplete chains, or self-signed certificates not in the trust store.


๐ŸŒ Real-World Applications: Where TLS Secures the Web: Real-World Applications

TLS is not just for web browsers โ€” it underpins virtually every secure channel on the modern internet.

HTTPS websites โ€” Every site with a padlock icon uses TLS. When you log in, check out, or submit a form, TLS ensures no one between your device and the server can read or tamper with the data in transit.

REST APIs and microservices โ€” When your mobile app calls a payment gateway, TLS encrypts the request and response. Inside Kubernetes clusters, services use mTLS (both sides present certificates) so that only authenticated services can communicate with each other.

Email delivery (SMTP with STARTTLS) โ€” Email servers use TLS to encrypt messages as they hop between mail servers, preventing ISPs or network attackers from reading your mail in transit.

IoT devices โ€” Smart thermostats, medical sensors, and security cameras transmit sensitive data over TLS (often TLS 1.3, valued for its smaller handshake footprint on memory-constrained hardware).

Zero-trust networks โ€” Corporate security architectures use mTLS to verify every service-to-service call, replacing "trust the internal network" with "trust only verified certificates."

ContextWhat TLS ProtectsVariant Used
Web browsersPage content + login credentialsHTTPS (TLS 1.3)
Mobile APIsRequest/response payloadsHTTPS or gRPC-TLS
Email serversMail in transit between serversSMTP + STARTTLS
IoT telemetrySensor data to cloudMQTT over TLS
Service meshService-to-service auth + encryptionmTLS (Istio, Linkerd)

The common thread: any channel where data could be intercepted or forged in transit is a candidate for TLS protection.


๐Ÿง  Deep Dive: Session Keys, Forward Secrecy, and Performance

ECDH and Perfect Forward Secrecy (PFS)

In TLS 1.3, the session key is derived via ECDHE (Elliptic Curve Diffie-Hellman Ephemeral). "Ephemeral" means a fresh key pair is generated for every session and discarded after.

Perfect Forward Secrecy: Even if an attacker records encrypted traffic today and steals the server's private key tomorrow, they cannot decrypt past sessions โ€” because the ephemeral ECDH keys are long gone.

TLS 1.2 without PFS (RSA key exchange): steal the private key โ†’ decrypt all stored traffic. This is why PFS is critical.

TLS Performance Cost

StageCost
Full handshake~1โ€“2 ms additional latency
Session resumption (TLS 1.3)~0.5 ms (1-RTT)
0-RTT resumption~0 ms extra, but has replay attack risk
Symmetric encryption (AES-GCM)Negligible โ€” hardware-accelerated on modern CPUs

The performance cost is dominated by the handshake. Session caching and TLS 1.3's 1-RTT largely eliminate this concern in production.


โš–๏ธ Trade-offs & Failure Modes: Common Misconfigurations and mTLS

MisconfigurationRiskFix
Expired certificateUsers see security warning; browsers blockAutomate renewal (Let's Encrypt + certbot)
TLS 1.0/1.1 enabledVulnerable to BEAST, POODLE attacksDisable; enforce TLS 1.2 minimum, prefer 1.3
Weak cipher suites (RC4, 3DES)Decryptable with modern hardwareRestrict to ECDHE + AES-256-GCM
Missing HSTS headerAllows SSL-stripping downgrade attacksSet Strict-Transport-Security: max-age=31536000

mTLS (Mutual TLS): In standard TLS, only the server presents a certificate. In mTLS, both client and server present certificates โ€” each verifies the other. Used in zero-trust networks, service meshes (Istio), and B2B APIs where you need cryptographic proof of client identity.

๐Ÿ“Š TLS Connection State Machine

stateDiagram-v2
    [*] --> Handshaking : TCP connected
    Handshaking --> Established : Finished messages exchanged
    Handshaking --> Failed : Cert invalid or cipher mismatch
    Established --> Closing : close_notify alert sent
    Closing --> Closed : close_notify received
    Failed --> [*]
    Closed --> [*]

The state machine highlights why TLS teardown requires an explicit close_notify alert rather than relying on a TCP FIN: without it, an attacker could inject a TCP RST to prematurely terminate the connection and silently truncate data โ€” a technique known as a truncation attack. A transition from Handshaking directly to Failed typically means certificate validation produced an error or the client and server could not agree on a common cipher suite; monitoring this ratio is the primary TLS health signal for any load balancer or API gateway. Only connections that reach Established have both sides cryptographically confirmed each other's Finished messages, providing assurance that the channel has not been tampered with.

๐Ÿ“Š mTLS Mutual Authentication Flow

sequenceDiagram
    participant C as Client (Service A)
    participant S as Server (Service B)

    C->>S: ClientHello + client cert request
    S->>C: ServerHello + Server Certificate
    C->>S: Client Certificate
    Note over C,S: Both verify each other's cert chains
    C->>S: Key Share + Finished
    S->>C: Finished
    Note over C,S: Encrypted channel  both identities verified

Standard TLS authenticates only the server โ€” the client's identity is left to the application layer (username/password, session token). mTLS elevates client authentication to the cryptographic layer: the server receives and validates the client's certificate chain against its own trusted CA store before the session key is finalised, and the client simultaneously does the same for the server. This symmetry is what makes mTLS the preferred authentication mechanism in zero-trust architectures and service meshes โ€” a service that does not hold a valid certificate issued by the cluster's internal CA simply cannot open a session, regardless of whether it knows the target's IP address or network credentials.


๐Ÿงญ Decision Guide: Configuring TLS for Your Use Case

Use TLS 1.3 whenever possible โ€” it's faster and more secure than 1.2. For public HTTPS, automate certificates with Let's Encrypt. Use mTLS when both sides need verified identities (internal microservices, B2B APIs). Always test with openssl s_client and an SSL grader (SSL Labs) before going live.


๐Ÿงช Checking and Configuring TLS in Practice

This example demonstrates a practical scenario. The code below shows the key implementation details you need to understand. Follow along to see how this works in practice.

Inspect a site's certificate from your terminal:

# View certificate details (subject, issuer, validity dates)
openssl s_client -connect google.com:443 -showcerts </dev/null 2>/dev/null \
  | openssl x509 -noout -text \
  | grep -E "Subject:|Issuer:|Not (Before|After)"

# Quick expiry check for your own domain
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \
  | openssl x509 -noout -dates

Minimal secure Nginx TLS configuration with Let's Encrypt:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # Enforce TLS 1.2 minimum; prefer TLS 1.3
    ssl_protocols TLSv1.2 TLSv1.3;

    # ECDHE ciphers only โ€” ensures Perfect Forward Secrecy
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

    # HSTS โ€” tells browsers to always use HTTPS for the next year
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

Automate certificate renewal (Let's Encrypt certificates expire every 90 days):

# Run renewal check twice daily via cron
0 3,15 * * * certbot renew --quiet --deploy-hook "nginx -s reload"

Common beginner mistake: Leaving TLS 1.0/1.1 enabled for "legacy browser compatibility." Both are deprecated and vulnerable to BEAST and POODLE attacks. Drop them โ€” all modern browsers support TLS 1.2+, and Let's Encrypt makes free certificates trivially easy to obtain and renew.


๐Ÿ› ๏ธ Spring Boot TLS & Let's Encrypt: Enabling HTTPS in Five Minutes

Spring Boot supports TLS natively โ€” configure it entirely in application.properties with no web server configuration files. Let's Encrypt provides free, automated 90-day certificates via the ACME protocol; certbot handles renewal with a single cron entry.

The example below covers the full path: a self-signed certificate for local development (zero cost, zero infrastructure), then a Let's Encrypt certificate for production โ€” both wired into Spring Boot with no Java code changes, only configuration.

# Step 1: Generate a self-signed certificate for local development (valid 90 days)
keytool -genkeypair \
  -alias     myapp \
  -keyalg    EC \
  -groupname secp384r1 \
  -validity  90 \
  -storetype PKCS12 \
  -keystore  src/main/resources/keystore.p12 \
  -storepass changeit \
  -dname "CN=localhost, OU=Dev, O=Acme, L=NYC, ST=NY, C=US"
# application.properties โ€” development: self-signed keystore
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=myapp

# Restrict to TLS 1.2+ โ€” disables BEAST/POODLE-vulnerable TLS 1.0/1.1
server.ssl.enabled-protocols=TLSv1.2,TLSv1.3
# Step 2 (production): Obtain a Let's Encrypt certificate
certbot certonly --standalone -d api.yourdomain.com

# Convert PEM to PKCS12 for Java keystores
openssl pkcs12 -export \
  -in  /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem \
  -inkey /etc/letsencrypt/live/api.yourdomain.com/privkey.pem \
  -out /etc/ssl/api-yourdomain.p12 \
  -name api -passout pass:changeit

# Automate renewal (Let's Encrypt certs expire every 90 days)
echo "0 3,15 * * * certbot renew --quiet --deploy-hook 'systemctl reload myapp'" | crontab -
# application.yml โ€” production: Let's Encrypt certificate
server:
  port: 8443
  ssl:
    enabled: true
    key-store: /etc/ssl/api-yourdomain.p12
    key-store-password: changeit
    key-store-type: PKCS12
    key-alias: api
    # ECDHE ciphers only โ€” ensures Perfect Forward Secrecy for every session
    ciphers: >
      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    enabled-protocols: TLSv1.2,TLSv1.3

The enabled-protocols and ciphers settings map directly to the TLS 1.3 concepts from this post: restricting to TLSv1.2,TLSv1.3 eliminates BEAST/POODLE; ECDHE-only ciphers ensure every session has Perfect Forward Secrecy (PFS), so past sessions stay safe even if the private key is later compromised.

For a full deep-dive on Spring Boot TLS configuration, mTLS between microservices, and automated Let's Encrypt certificate renewal with Cert-Manager in Kubernetes, a dedicated follow-up post is planned.


๐Ÿ“š Five Lessons TLS Teaches About Secure-by-Default Design

  1. Don't confuse confidentiality with authentication. TLS encrypts traffic so it cannot be read (confidentiality), but the certificate tells you who you are talking to (authentication). Both matter, and TLS provides both.

  2. Asymmetric encryption bootstraps the secret โ€” it doesn't encrypt your data. A common misconception is that RSA encrypts your messages. It doesn't. It securely establishes the session key. AES does the actual data encryption.

  3. Let's Encrypt killed the "certificates are expensive" excuse. Free, automated 90-day certificates mean there is no valid reason to serve HTTP in 2025. Every site should have TLS.

  4. Certificate expiry causes real outages. Automate renewal with certbot or your cloud provider's certificate manager. Treat a manual certificate as a risk, not a cost-saving measure.

  5. TLS protects the channel, not the endpoints. If your server is compromised or your application stores passwords in plaintext, TLS cannot help. Encryption in transit is one layer of defense โ€” not a complete security strategy.


๐Ÿ“Œ TLDR: Summary & Key Takeaways

  • Two-phase encryption: Asymmetric (RSA/ECDH) for key exchange; Symmetric (AES-GCM) for data.
  • TLS 1.3 handshake: 1 RTT, ECDHE key exchange, mutual Finished verification.
  • Chain of Trust: Root CA โ†’ Intermediate CA โ†’ Leaf Certificate. Browser validates all links.
  • Perfect Forward Secrecy: Ephemeral ECDH keys mean past sessions stay safe even if the server key is later compromised.
  • mTLS: Both sides authenticate โ€” used in zero-trust and service mesh architectures.


Share

Test Your Knowledge

๐Ÿง 

Ready to test what you just learned?

AI will generate 4 questions based on this article's content.

Abstract Algorithms

Written by

Abstract Algorithms

@abstractalgorithms