TLS 1.2 vs TLS 1.3:握手轮次、安全性与性能对比
聊到 TLS 版本选择,很多人第一反应是“用新的总没错”。但实际落地的时候,我见过不少团队因为兼容性或者“用习惯了”而死守 TLS 1.2。说实话,这两个版本差距真的很大。从通到专,我们一条一条拆开看。
握手轮次:少一次,快一倍
这是最直观的差异。我习惯用一个比喻:TLS 1.2 握手像两个人互相传纸条确认身份,来回至少跑两次高铁;TLS 1.3 像直接刷脸,一次搞定。
TLS 1.2 的 2-RTT 开销
你想想看,一个完整 TLS 1.2 握手,客户端和服务端至少要交换两次网络包。
- 第一次:ClientHello → ServerHello + Certificate + ServerHelloDone
- 第二次:ClientKeyExchange + ChangeCipherSpec + Finished → Finished
这还没算证书链传递和密钥协商的计算时间。对于高延迟链路,这个 2-RTT 代价很痛苦。
TLS 1.3 的 1-RTT 优势
TLS 1.3 把流程压缩了。关键改动是——客户端直接带密钥参数一起发出去。
- 客户端在 ClientHello 里就包含了密钥协商参数
- 服务端收到后可以直接算密钥,并在 ServerHello 里带上自己的参数和完成消息
- 整个过程只需要一次来回
这还没完。TLS 1.3 还支持 0-RTT 模式,前提是你之前已经跟这个服务器握过手。我优化过一个跨国 API 网关,当时 0-RTT 加持后,握手延迟从 200ms 降到 15ms 左右。
如果你做的是 Web 高频接口,1-RTT vs 2-RTT 差异不明显。但如果是物联网设备、移动端长轮询或金融高频交易,少一次 RTT 能直接改变用户体验。我曾经帮一个移动端 SDK 项目做升级,TLS 1.3 切过去后,冷启动握手时间从 280ms 降到了 110ms。
安全性:砍掉旧套件,减少攻击面
安全性这块,TLS 1.3 可以说是“大清洗”。它去掉了一大堆老旧、不安全的密码套件。
TLS 1.2 的“兼容性包袱”
TLS 1.2 为了兼容,保留了 CBC 模式、RC4、3DES 这些已经被淘汰的加密方式。我刚才说的那句话你可能觉得挺轻描淡写的,但实际在安全审计时,这些遗留套件就是重灾区。
- CBC 模式:存在 Padding Oracle 攻击风险
- RC4:早就被证明有偏倚攻击
- 3DES:56 位密钥强度已经不够
- 没有强制要求前向安全
TLS 1.3 的“强制前向安全”
TLS 1.3 只保留了 AEAD 模式(GCM、CCM、Poly1305),且强制使用前向安全。
什么叫前向安全?说白了,就算攻击者拿到了你服务器的私钥,也无法解密之前记录的通信内容。为什么?因为会话密钥是通过临时密钥协商的,私钥跟它没关系。
TLS 1.3 还移除了静态 RSA 密钥交换,这就是前向安全能实现的根本原因。我参与过一个金融系统的合规项目,当时监管要求必须支持前向安全。如果系统跑的是 TLS 1.2,配置起来又臭又长;TLS 1.3 开箱自带,省了很多事。
我见过一个团队,为了兼容旧设备,在 TLS 1.3 服务器上又开着 TLS 1.2,并且配了很不安全的套件。结果是——攻击者可以直接降级到 TLS 1.2 来攻击你。说白了,安全链条取决于最弱的一环。正确做法是:如果必须兼容旧设备,请单独维护一个降级端口,主端口只开 TLS 1.3。
性能:从协议层优化到底层逻辑
性能差异不仅仅是少一次 RTT。我们从计算开销、证书处理、会话恢复三个角度来对比。
| 对比维度 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手轮次 | 2-RTT(完整) | 1-RTT(完整),0-RTT(恢复) |
| 密码套件数量 | 30+ 种 | 5 种 |
| 前向安全 | 可选 | 强制 |
| 证书传递 | 全部证书链明文传递 | 证书链可加密传递 |
| 0-RTT 支持 | 不支持 | 支持 |
| 计算开销 | 密钥协商 + MAC 计算分离 | 一次密钥协商 + AEAD 整合 |
再看一个具体的例子。我优化过一个 CDN 边缘节点,在切换 TLS 1.3 后,CPU 使用率下降了约 12%。原因很简单——
- 证书处理简化:TLS 1.2 需要全链路验证证书链,服务端要把根证书到服务器证书全部发出去,客户端再逐个验证。TLS 1.3 允许证书加密传输,且减少了非必要中断。
- 密码套件少了:协商时间缩短,再也不需要从几十个套件里挑一个。
- 计算整合:AEAD 模式将加密、认证、完整性校验合并,一步到位。
这还没算会话恢复成本。TLS 1.2 的会话恢复依赖 Session ID 或 Session Ticket,需要额外存储。TLS 1.3 的 PSK(Pre-Shared Key)机制更轻量,直接在握手时复用。
代码实践:如何优雅地切换版本
别关说不练。我贴一段 Nginx 里的配置片段,你可以直接参考。
# 正确的配置方式:优先 TLS 1.3,降级到 TLS 1.2
ssl_protocols TLSv1.2 TLSv1.3;
# 只保留安全的密码套件(支持 TLS 1.3 的服务端只需配 1.2 部分)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# 强制前向安全(其实 TLS 1.3 本身就是强制前向安全,但为了兼容 1.2 时避免弱套件)
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
注意,这里 ssl_protocols 我写了两个版本。这是为了做平滑过渡。但你要留意:1.2 和 1.3 同时开启时,客户端会优先选 1.3。如果客户端只支持 1.2,也能谈下来——只是性能差一些。
生产环境中,尽量只开 TLS 1.3。如果确实有设备兼容问题(比如老旧 Android、Windows XP),再考虑开 1.2,但要禁止弱套件。不要把 1.1 或 1.0 放出来。
SVG:TLS 1.2 vs TLS 1.3 握手流程对比
从这张图能直观看到差异:左边 TLS 1.2 来回折腾四次消息包裹(实际算上握手完成确认,是 2 次完整往返),右边 TLS 1.3 压缩到一次半。而且 1.3 还去掉了独立的证书传输块,把证书相关数据隐藏在握手消息里,既减少开销又增强隐私。
总结对比表:几个关键决策点
| 场景 | 推荐版本 | 原因 |
|---|---|---|
| 新建系统 | TLS 1.3 | 安全性、性能全面领先,无历史包袱 |
| 兼容 IoT 旧设备 | TLS 1.2 + 禁用弱套件 | 许多老旧芯片组只支持 1.2 或更低 |
| 金融/支付合规 | TLS 1.3 或 1.2 前向安全 | 监管明确要求前向安全 |
| 公有云 CDN | TLS 1.3 | 0-RTT 能显著降低首屏延迟 |
| 内部微服务 | TLS 1.3 | 减少握手开销,提高 RPS |
说白了,你内心要知道:能上 1.3 就别犹豫。如果条件不允许,那就把 1.2 的弱配置全部关掉。千万别因为“我怕麻烦”而开着旧版本的安全漏洞。
任何生产环境,TLS 版本不要低于 1.2。不要以为内网就不需要——我曾经见过内网服务被监听,就是因为还在用 TLS 1.0 的 RC4。内网渗透的第一步就是嗅探弱加密。