TLS 1.3 的革命性改进

TLS 1.3 是 TLS 协议的重大升级,主要改进:

  1. 握手延迟降低:3-RTT → 1-RTT(首次),0-RTT(恢复)
  2. 移除不安全算法:RC4、3DES、CBC 模式、SHA-1 等
  3. 强制前向保密:所有密码套件都支持 PFS
  4. 简化密码套件:从 300+ 减少到 5 个

TLS 1.2 vs TLS 1.3

握手对比

TLS 1.2 握手 (2-RTT):
客户端 → 服务器: ClientHello (支持的密码套件列表)
服务器 → 客户端: ServerHello + Certificate + ServerKeyExchange + ServerHelloDone
客户端 → 服务器: ClientKeyExchange + ChangeCipherSpec + Finished
服务器 → 客户端: ChangeCipherSpec + Finished

TLS 1.3 握手 (1-RTT):
客户端 → 服务器: ClientHello + KeyShare
服务器 → 服务器: ServerHello + KeyShare + Certificate + Finished

密码套件对比

TLS 1.2 密码套件 (部分):
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
... (300+ 种)

TLS 1.3 密码套件 (全部):
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256
TLS_AES_128_CCM_8_SHA256

TLS 1.3 握手详解

完整握手流程

步骤 1: ClientHello
┌─────────────────────────────────────────┐
│ 协议版本: TLS 1.3                        │
│ 随机数: 32 字节随机值                    │
│ 密码套件: [TLS_AES_256_GCM_SHA384, ...] │
│ 扩展:                                    │
│   - key_share: X25519 公钥              │
│   - supported_versions: TLS 1.3         │
│   - signature_algorithms: ecdsa_secp256 │
└─────────────────────────────────────────┘

步骤 2: ServerHello
┌─────────────────────────────────────────┐
│ 协议版本: TLS 1.3                        │
│ 随机数: 32 字节随机值                    │
│ 密码套件: TLS_AES_256_GCM_SHA384        │
│ 扩展:                                    │
│   - key_share: X25519 公钥              │
│   - encrypted_extensions: 加密扩展       │
│   - certificate: 服务器证书              │
│   - certificate_verify: 签名验证         │
│   - finished: HMAC 验证                  │
└─────────────────────────────────────────┘

步骤 3: 客户端验证
┌─────────────────────────────────────────┐
│ 验证服务器证书                           │
│ 验证签名                                 │
│ 生成会话密钥                             │
│ 发送 Finished                           │
└─────────────────────────────────────────┘

密钥交换

X25519 密钥交换:
客户端生成: a (私钥), A = a * G (公钥)
服务器生成: b (私钥), B = b * G (公钥)

共享密钥: S = a * B = b * A = a * b * G

前向保密:
即使服务器私钥泄露,过去的会话密钥也无法计算

前向保密(PFS)

什么是前向保密

无 PFS:
服务器私钥 → 解密所有历史会话

有 PFS:
服务器私钥 → 无法解密历史会话
每次会话使用临时密钥 → 密钥不重复使用

ECDHE 实现

ECDHE (Elliptic Curve Diffie-Hellman Ephemeral):
每次握手生成新的临时密钥对
会话密钥 = 私钥 * 对方公钥
私钥用完即丢弃

0-RTT 恢复

会话票据

首次连接:
客户端 → 服务器: ClientHello
服务器 → 客户端: ServerHello + NewSessionTicket
客户端保存: 会话票据 + PSK (预共享密钥)

恢复连接:
客户端 → 服务器: ClientHello + PSK + 0-RTT 数据
服务器 → 客户端: ServerHello + Finished + 0-RTT 数据

0-RTT 的安全风险

重放攻击:
攻击者截获 0-RTT 数据 → 重放给服务器

防御措施:
1. 只允许幂等请求(GET、HEAD)
2. 服务器维护 0-RTT 数据 nonce 池
3. 限制 0-RTT 数据大小

密码学基础

对称加密

AES-GCM:
- 加密: AES-128/256-GCM
- 认证: GCM 模式提供完整性
- 性能: 硬件加速(AES-NI)

ChaCha20-Poly1305:
- 加密: ChaCha20 流密码
- 认证: Poly1305 MAC
- 优势: 无硬件加速时更快

非对称加密

ECDH 密钥交换:
- 曲线: X25519、P-256、P-384
- 安全性: 基于椭圆曲线离散对数问题
- 性能: 比 RSA 快 10 倍以上

数字签名:
- 算法: ECDSA、EdDSA
- 用途: 验证证书真实性

实战配置

Nginx TLS 1.3 配置

server {
    listen 443 ssl;
    
    # TLS 版本
    ssl_protocols TLSv1.3;
    
    # 密码套件
    ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    
    # 证书
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 会话配置
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
}

证书生成

# 生成 ECC 密钥
openssl ecparam -genkey -name prime256v1 -out server.key

# 生成 CSR
openssl req -new -key server.key -out server.csr

# 自签名证书
openssl req -x509 -nodes -days 365 -newkey ec:<(openssl ecparam -name prime256v1) \
  -keyout server.key -out server.crt

面试常见问题

  1. TLS 1.3 为什么更快?

    • 减少握手轮次(1-RTT vs 2-RTT)
    • 使用更快的密码算法(AES-NI、X25519)
    • 支持 0-RTT 恢复
  2. 前向保密如何实现?

    • 使用临时密钥交换(ECDHE)
    • 每次会话生成新密钥
    • 私钥用完即丢弃
  3. 0-RTT 的局限性?

    • 可能被重放攻击
    • 只能发送幂等请求
    • 服务器需要额外验证
  4. TLS 1.3 的密码套件为什么这么少?

    • 移除不安全算法
    • 简化配置,减少错误
    • 所有套件都支持 PFS

调试工具

# 测试 TLS 配置
openssl s_client -connect example.com:443 -tls1_3

# 查看证书链
openssl s_client -connect example.com:443 -showcerts

# 测试密码套件
nmap --script ssl-enum-ciphers -p 443 example.com

# 在线工具
# https://www.ssllabs.com/ssltest/