🔐 Behind the Padlock: How TLS 1.3 Silently Guards HTTPS

The new rules of encryption, performance, and trust-building in the web’s most critical protocol.

On the internet, messages from your device travel through many routers, ISPs, and international cables. With HTTP, data travels unprotected. It’s like sending a transparent and unsealed envelope through the mail.

When you send sensitive information online (like credit card details or login credentials), you don’t want anyone on the route to read your data, or tamper with it (for example, by injecting malware), or pretend to be the website you’re visiting (phishing). While HTTP doesn’t prevent any of these from happening, HTTPS uses a security protocol that protects communication between your browser and servers worldwide. This security protocol is called TLS (Transport Layer Security), and it protects your data when it moves across the internet.

HTTPS is essentially HTTP over TLS, that is, the same HTTP request but encrypted, protected, and verified using TLS. HTTPS uses port 443 instead of the HTTP port 80.

In the OSI model, TLS sits between the application layer and the transport layer. Think of TLS as a security guard standing between your app and the network. It secures HTTP data sent by applications (in the application layer) before passing it to the web server working at the transport layer. TLS effectively provides three key guarantees:

  1. Confidentiality: TLS scrambles (encrypts) your data in a way that only the intended recipient can unscramble (decrypt) it. In a real world analogy, TLS locks your letter in a box and only the intended recipient has the key.
  2. Integrity: TLS ensures that your data can’t be changed in transit and if someone tries, it would be detected. It’s like sealing your letter with wax - if it’s broken, you know it was tampered with.
  3. Authentication: To make sure that you’re not sending sensitive information to an imposter, TLS verifies the website’s digital certificate (like an ID badge).

There are two commonly used types of encryption:

  1. Symmetric Encryption: Imagine locking your letter in a box that can be locked and unlocked with the same key. Both the sender and the recipient own a copy of this key.
  2. Asymmetric Encryption: Imagine locking a box with one key, but needing a different key to unlock it. The sender uses a locking key, and only the recipient has the correct key to open it.

In this post, we’ll focus on TLS 1.3 - the latest and most secure version of the protocol. While TLS 1.3 offers the most security, its adoption is still ongoing, and older versions of TLS, like TLS 1.2, are still widely used.

How TLS 1.3 works:

Before any encrypted data gets exchanged, there’s a TLS handshake - it’s like a conversation starter between a client (like your browser) and a server (like https://example.com). The handshake’s job is to:

  • Help both sides prove their identity
  • Let them agree on a shared secret key for encryption
  • Ensure no one can eavesdrop, tamper, or replay the conversation

TLS 1.3 simplifies the handshake process to just three steps:

1. ClientHello (Client -> Server)


H1

The client kicks things off by generating a temporary key pair (a private key + public key) using elliptic curve cryptography. It then sends the server:

  • The generated public key
  • A list of supported cipher suites (encryption methods)
  • The highest TLS version it supports
  • A random number (used later during key derivation)

All of this is unencrypted.

2. ServerHello + Encrypted Handshake (Server -> Client)

Now it’s the server’s turn to respond.

2.1 ServerHello


H2

The server also generates its own temporary key pair and sends back:

  • The server generated public key
  • The chosen cipher suite (picked from the client’s list)
  • Another random number

This part is still unencrypted.

2.2. Deriving the Handshake Keys


H3

Both sides now have what they need to compute a shared secret. Using the Ephemeral Diffie-Hellman algorithm (usually ECDHE), each side combines:

  • Its own private key
  • The other party’s public key

This results in a shared secret seed (also referred to as shared secret). Thanks to the magic of ECDHE, both sides arrive at the same secret without ever sending it over the network. Even if someone were watching, they couldn’t derive the secret because private keys never leave the respective devices. It’s like two people using a secret recipe that creates the same dish but never sharing the ingredients.

Next, both sides feed this seed into HKDF (a Key Derivation Function). HKDF uses:

  • The shared secret seed
  • A transcript hash (a digest of the handshake so far)
  • A context label like tls13 finished or tls13 c hs traffic

From this, they generate encryption keys:

  • client_handshake_traffic_key: Generated using the context label tls13 c hs traffic. Used for encrypting and decrypting client -> server messages
  • server_handshake_traffic_key: Generated using the context label tls13 s hs traffic. Used for encrypting and decrypting server -> client messages

These keys are computed independently on both sides but are identical due to the shared inputs.

📝 Note: While the random numbers sent in ClientHello and ServerHello aren’t direct inputs to computation of the raw seed, they do influence all derived secrets through the transcript hash. Thus, they ensure that each session has a unique context, even if the same ECDHE keys were (hypothetically) reused.

2.3. Encrypted Handshake Begins


H4

The server now uses the server_handshake_traffic_key to encrypt the next set of messages:

  • Digital certificate: This is like a passport issued by a trusted authority (a Certificate Authority or CA). It includes the domain, the server’s public key, the issuing CA, validity dates, and a digital signature (encrypted using the CA’s private key and can be unencrypted using its public key). The client browser can verify the signature using the CA’s public key, which is built into the browser.
  • CertificateVerify: A digital signature encrypted using the server’s private key. This can be decrypted using the public key of the server in the certificate.
  • Finished message: This is a MAC (Message Authentication Code), generated using a special Finished key (derived via HKDF from the server’s secret server_handshake_traffic_secret + the handshake transcript). It proves that the server has the correct secrets and hasn’t tampered with anything.

3. Finish (Client → Server)

3.1 Client Verifies Server Identity


H5

The client decrypts the server’s messages using the server_handshake_traffic_key, then performs several checks:

  • Is the TLS certificate still valid?
  • Was it issued by a trusted CA?
  • Does it match the domain name of the server?
  • Is the CA’s digital signature valid?
  • Can it verify the server’s signature (CertificateVerify) using the public key from the certificate?

It also verifies the server’s Finished MAC by generating its own version of the Finished key and comparing the MACs.

If anything’s off, the client aborts the handshake and shows an error like “Connection not secure”.

3.2 Client Sends Finished


H6

If everything checks out, the client sends its own Finished message, encrypted with the client_handshake_traffic_key. This message:

  • Proves to the server that the client has derived the correct keys
  • Confirms that the client trusts the server’s identity

Only once this is done can encrypted communication begin.

Post Handshake


PH

With the handshake complete, both the client and server derive a new set of encryption keys, called the application traffic keys. They’re based on the same shared secret seed from the handshake, but with different context labels:

  • client_application_traffic_key: Encrypts and decrypts messages from client -> server
  • server_application_traffic_key: Encrypts and decrypts messages from server -> client

From this point forward, all communication is encrypted using these symmetric keys. That means the same key is used to encrypt and decrypt a given message (as opposed to asymmetric cryptography, where encryption and decryption keys are different).

So, in TLS 1.3:

  • Asymmetric encryption is used only during the handshake, to establish trust (certificate verification) and derive a shared secret seed.
  • Symmetric encryption is used afterward for fast, secure communication.

TLS 1.3 = 1-RTT Handshake

While a TCP handshake technically involves 1.5 round trips, TLS 1.3 is known as a 1-RTT protocol, because:

  • By the end of the second flight (when the server responds), both parties already have all they need to derive the application keys.
  • The client’s first actual request can be sent together with its Finished message, piggybacking on that final handshake step. So, there’s no need to wait for another round trip before starting secure data transfer.

Other Keys Used in TLS 1.3

TLS 1.3 also defines additional types of keys beyond the main handshake and application keys:

  • Resumption Key: TLS 1.3 allows the browser to resume a session without repeating the full handshake, by sending a resumption master secret (a temporary one-time use only pass that only works if the browser comes back soon). From that, the server generates a resumption key that lets the browser connect quickly and securely.
  • Key Update Keys: For long-lived sessions, TLS 1.3 supports key updates. Both parties can periodically generate new application traffic keys, reducing the risk of long-term key compromise.

What’s the Point of So Much Randomness?

Randomness is at the heart of TLS 1.3’s security. Here’s why it matters:

1. Unique Keys for Every Session

Each handshake generates a fresh ephemeral key pair, leading to a new shared secret seed and new encryption keys. This ensures:

  • Every session is isolated.
  • A hacker can’t use data from one session to crack another.

2. No Replay Attacks

A replay attack is when someone reuses past messages to impersonate a client. For example, a hacker might try to log into your Gmail account by resending yesterday’s login messages. That won’t work in TLS 1.3 because:

  • Each session uses new ephemeral keys.
  • That results in a different shared secret seed and different encryption keys.
  • The attacker’s replayed messages won’t produce the correct Finished MAC, so the server aborts the connection immediately.

3. Forward Secrecy

TLS 1.3 ensures forward secrecy, which means:

  • Encryption keys are never stored.
  • If someone steals your server’s long-term private key later, they still can’t decrypt past sessions, because session specific secrets are gone forever.

It’s like burning both the lock and the key after each session - no one can ever reconstruct them.

4. Freshness in Resumed Sessions

Even during session resumption, TLS 1.3 introduces fresh randomness. So while the client and server can skip parts of the handshake, they don’t reuse the same keys. That keeps resumed sessions just as secure as new ones.

Session Resumption in TLS 1.3

When you visit a website over HTTPS, your browser and the server perform a full TLS 1.3 handshake - exchanging keys, verifying identities, and setting up encryption. This ensures privacy and trust but takes a bit of time and computing effort. If you connect soon after, TLS session resumption lets you skip parts of that handshake, saving time, computing power, and bandwidth, without compromising security.

1. Issuing the Session Ticket


RS1

Once a full handshake is complete, both client and server derive a shared secret called the resumption master secret using HKDF and their handshake secrets. The server then derives a resumption_psk PSK (Pre-Shared Key) from this master secret, again using HKDF.

It then sends the client a NewSessionTicket message, which includes:

  • ticket: A blob that encodes the PSK (opaque to the client)
  • ticket_lifetime: How long the ticket is valid
  • ticket_age_add: A random offset added to the client’s clock for security
  • ticket_nonce: A unique value used when deriving the PSK
  • ticket_id: A unique identifier for this session ticket

This message is sent after the handshake and is encrypted using the application traffic keys.

The client receives and decrypts the message but it doesn’t decrypt the ticket. Instead it stores ticket_id, ticket and associated metadata for future use.

2. Reconnecting with PSK and Binder


RS2

When the client reconnects to the server, it sends a ClientHello message, just like it would in a full handshake (including a new public key derived using elliptic curve math). But this time, it includes a pre_shared_key extension, containing:

  • One or more PSK identities (ticket IDs from earlier sessions)
  • Corresponding binders, one for each PSK

For every PSK identity, the client computes a binder using the current ClientHello transcript hash (transcript_hash):

early_secret_seed = HKDF-Extract(salt=0, resumption_psk)
binder_key = HKDF-Expand(early_secret_seed, "resumption binder", "", num_bytes_output)
binder = HMAC(binder_key, transcript_hash)

The binder proves that the client possesses the secret resumption_psk associated with the ticket.

3. Server Verifies the Binder


RS3

The server receives the ClientHello and checks for the pre_shared_key extension. It examines each PSK identity in order of client preference. For each one:

  • It checks if it still has the corresponding session ticket
  • Verifies the ticket’s validity (authenticity, expiration, etc.)
  • Recomputes the binder using its own copy of the resumption_psk
  • Compares the computed binder with the one sent by the client

If the binder matches, it means the client possesses the correct PSK, and the server selects this PSK for resumption.

The server then responds with a ServerHello, containing:

  • The index of the accepted PSK identity (from the client’s list)
  • A new ephemeral public key (generated using ECDHE)

No certificate is sent during resumption as it is assumed that the client already trusts the server based on the earlier full handshake.

4. PSK + ECDHE Key Derivation and Completion


RS4

At this point, both sides have:

  • Their own ephemeral key pair (freshly generated)
  • The other side’s ephemeral public key
  • A shared PSK (from the session ticket)

Using these, the client and server perform a fresh ECDHE exchange, and combine it with the PSK (in multiple stages, not as a single blob) to derive:

  • A new shared secret seed
  • Fresh handshake traffic keys
  • New application traffic keys
  • Finished keys, MAC keys, etc.

The server sends a Finished message encrypted using the new server_handshake_traffic_key, and the client replies with its own Finished. Once that’s done, they can immediately begin encrypted application data exchange, just like in a full handshake.

TLS 1.3 may seem intimidating at first glance, but once you break it down into its handshake steps, key derivation process, and session resumption mechanics, it becomes a clear example of elegant security by design. Whether you’re building APIs, debugging HTTPS issues, or just trying to understand what’s going on beneath the padlock icon in your browser, TLS 1.3 is a foundational piece of modern internet security.

Happy (secure) building!