TLS 1.3 的革命性改进
TLS 1.3 是 TLS 协议的重大升级,主要改进:
- 握手延迟降低:3-RTT → 1-RTT(首次),0-RTT(恢复)
- 移除不安全算法:RC4、3DES、CBC 模式、SHA-1 等
- 强制前向保密:所有密码套件都支持 PFS
- 简化密码套件:从 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
面试常见问题
TLS 1.3 为什么更快?
- 减少握手轮次(1-RTT vs 2-RTT)
- 使用更快的密码算法(AES-NI、X25519)
- 支持 0-RTT 恢复
前向保密如何实现?
- 使用临时密钥交换(ECDHE)
- 每次会话生成新密钥
- 私钥用完即丢弃
0-RTT 的局限性?
- 可能被重放攻击
- 只能发送幂等请求
- 服务器需要额外验证
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/