TLS / HTTPS

What Is TLS 1.3 and Why It Matters for Your Web App

TLS 1.3 is faster and more secure than TLS 1.2. Learn what changed, how the handshake works, which cipher suites it uses, and how to enable it on your server today.

February 3, 20265 min readShipSafer Team

TLS 1.3, standardized in RFC 8446 in 2018, is the current version of the Transport Layer Security protocol. It's both faster and significantly more secure than its predecessor TLS 1.2 — yet many servers still serve TLS 1.2 or older by default.

This guide explains what changed in TLS 1.3, why it matters, and how to check and enable it on your own infrastructure.

TLS 1.3 vs TLS 1.2: What Actually Changed

1. Faster Handshake (1-RTT vs 2-RTT)

TLS 1.2 requires two round trips before the first application data can be sent. TLS 1.3 cuts this to one round trip (1-RTT), reducing latency by one full network round-trip on every new connection.

For users connecting from high-latency networks (mobile, international), this is a meaningful improvement.

TLS 1.2 handshake:
  Client → Server: ClientHello
  Server → Client: ServerHello, Certificate, ServerHelloDone
  Client → Server: ClientKeyExchange, ChangeCipherSpec, Finished
  Server → Client: ChangeCipherSpec, Finished
  [2 round trips before data flows]

TLS 1.3 handshake:
  Client → Server: ClientHello + key share
  Server → Client: ServerHello + key share + Certificate + Finished
  Client → Server: Finished + application data
  [1 round trip before data flows]

2. 0-RTT Session Resumption

TLS 1.3 supports 0-RTT resumption for returning connections, sending application data in the very first message. This eliminates handshake latency entirely for repeat visitors.

Important caveat: 0-RTT data is vulnerable to replay attacks. Only use 0-RTT for idempotent requests (GET, HEAD) — never for state-changing operations.

3. Removed Weak Cryptography

TLS 1.3 eliminates all the cipher suites that made TLS 1.2 vulnerable to well-known attacks:

Removed from TLS 1.3Attack it enabled
RSA key exchangeBEAST, FREAK
CBC mode ciphersPOODLE, Lucky13
RC4RC4 attacks
SHA-1Collision attacks
MD5Collision attacks
Export-grade ciphersFREAK, Logjam
DH parameters < 2048-bitLogjam

TLS 1.3 only supports three cipher suites, all of which use AEAD encryption:

  • TLS_AES_256_GCM_SHA384
  • TLS_AES_128_GCM_SHA256
  • TLS_CHACHA20_POLY1305_SHA256

4. Forward Secrecy is Mandatory

TLS 1.2 allows RSA key exchange, which does not provide forward secrecy. If an attacker records your TLS traffic today and later obtains your private key, they can decrypt all past sessions.

TLS 1.3 mandates ephemeral Diffie-Hellman (ECDHE) key exchange for all sessions, which means each session uses a unique key. Past sessions cannot be decrypted even with the server's private key.

5. Encrypted Handshake

In TLS 1.2, the server's certificate is sent in plaintext during the handshake. In TLS 1.3, the certificate and most of the handshake are encrypted. This reduces information leakage to passive observers on the network.

How to Check Your Server's TLS Version

Using openssl

openssl s_client -connect yourdomain.com:443 -tls1_3 2>&1 | grep "Protocol"

If you see Protocol : TLSv1.3, TLS 1.3 is supported and was negotiated.

To check which TLS versions are supported:

# Test TLS 1.3
openssl s_client -connect yourdomain.com:443 -tls1_3 < /dev/null 2>&1 | grep "Protocol\|Cipher"

# Test TLS 1.2
openssl s_client -connect yourdomain.com:443 -tls1_2 < /dev/null 2>&1 | grep "Protocol\|Cipher"

# Test old TLS 1.1 (should fail on well-configured servers)
openssl s_client -connect yourdomain.com:443 -tls1_1 < /dev/null 2>&1 | grep "Protocol\|Cipher"

Using nmap

nmap --script ssl-enum-ciphers -p 443 yourdomain.com

This shows all TLS versions and cipher suites supported by the server.

Enabling TLS 1.3

nginx

server {
    listen 443 ssl;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;

    # TLS 1.3 session tickets
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
}

Apache

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off

Node.js

Node.js enables TLS 1.3 by default as of Node.js 12+ (using OpenSSL 1.1.1+). You can verify:

const tls = require('tls');
console.log(tls.DEFAULT_MAX_VERSION); // 'TLSv1.3' on Node 12+

To restrict to TLS 1.3 only:

const server = https.createServer({
  minVersion: 'TLSv1.2',
  maxVersion: 'TLSv1.3',
  // ...
});

Which TLS Versions Should You Support?

VersionRecommendation
TLS 1.3Always enable
TLS 1.2Keep enabled for compatibility (most clients support it)
TLS 1.1Disable — deprecated by RFC 8996
TLS 1.0Disable — deprecated by RFC 8996, required for PCI-DSS compliance
SSLv3Disable immediately — broken protocol

For most web apps, supporting TLS 1.2 + TLS 1.3 is the right balance. Dropping TLS 1.2 would break compatibility with older Android devices, enterprise Java clients, and some embedded systems.

What TLS 1.3 Doesn't Fix

TLS 1.3 secures the transport layer. It doesn't protect against:

  • Application-layer vulnerabilities (SQL injection, XSS, CSRF)
  • Weak certificate issuance (certificate transparency solves this partially)
  • Misconfigurations at the application layer (mixed content, insecure cookies)
  • Endpoint compromise

TLS 1.3 is a necessary foundation, not a complete security solution.

tls
https
ssl
encryption
web-security

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.