TLS 1.3 is the biggest overhaul of TLS in two decades, and the most surprising thing about it is how much less it does, and how much faster it is because of it.

Let’s see it in action. Imagine a client (your browser) and a server (a website).

Client: "Hey server, I want to talk TLS 1.3." Server: "Great! Here’s my certificate, and I support these cipher suites for TLS 1.3." Client: "Okay, I’ve verified your cert. I choose this cipher suite. Let’s encrypt!"

That’s it. The whole handshake, including key exchange and agreeing on encryption, now takes one round trip between client and server. For comparison, TLS 1.2 often took two or even three round trips. This speedup is thanks to a few key changes:

  • Combined Key Exchange and Authentication: In TLS 1.2, the client would authenticate the server, then the client and server would exchange keys. TLS 1.3 does both in the first message from the client.
  • Fewer Cipher Suites: TLS 1.3 mandates a smaller, more secure set of cipher suites. Many older, weaker ones are gone. This simplifies negotiation.
  • Removed Obsolete Features: Features like compression and renegotiation, which had security vulnerabilities, are gone.

To implement TLS 1.3, you primarily need to configure your web server (like Nginx or Apache) and ensure your clients (browsers, applications) support it.

For Nginx, you’d modify your ssl_protocols directive. Instead of:

ssl_protocols TLSv1.2;

You’d use:

ssl_protocols TLSv1.3 TLSv1.2;

This tells Nginx to prefer TLS 1.3 if the client supports it, but to fall back to TLS 1.2 for older clients.

For Apache, it’s similar:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1

becomes:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2 # For TLS 1.3 only
# or
SSLProtocol all -SSLv3 # For TLS 1.2 and TLS 1.3

The first example forces TLS 1.3, which is aggressive but might break older clients. The second example enables TLS 1.3 alongside TLS 1.2.

The biggest hurdle, and the reason for the TLSv1.2 in the configuration, is backward compatibility. Most modern browsers and operating systems support TLS 1.3. However, older clients or specific embedded systems might not. By including TLSv1.2 (or all -SSLv3 for Apache), you ensure that connections from these older clients can still succeed. The server and client will negotiate down to the highest common protocol version they both support.

The magic of TLS 1.3’s speedup lies in its handshake. The server sends its certificate and supported cipher suites in its ServerHello message. The client, upon receiving this, can immediately select a cipher suite and send its Finished message, which includes the encrypted handshake key. This means the client doesn’t have to wait for the server to send its key, and the server doesn’t have to wait for the client to send its key before they can start encrypting application data. This is a significant departure from TLS 1.2, where the client would first receive the server’s certificate, then send its ClientKeyExchange message, and then the server would send its ChangeCipherSpec and Finished messages. TLS 1.3 collapses these steps.

The most overlooked aspect of TLS 1.3 is how it handles cipher suites. Instead of the client and server negotiating a specific combination of key exchange, bulk encryption, and message authentication code (MAC) algorithms as in TLS 1.2, TLS 1.3 uses pre-defined, authenticated encryption modes. The client advertises which of these modes it supports, and the server picks one. This drastically reduces the attack surface by eliminating weak or deprecated algorithms and simplifying the negotiation process. For example, the client might offer TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, or TLS_AES_128_GCM_SHA256. The server selects one, and that’s it.

The next step is understanding the impact of TLS 1.3 on network middleboxes and how to debug potential compatibility issues.

Want structured learning?

Take the full Tls-ssl course →