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 vs TLS 1.3 握手流程对比 TLS 1.2 握手 (2-RTT) ClientHello ServerHello + Certificate ClientKeyExchange ChangeCipherSpec + Finished 安全通信开始 总计 2 次网络往返 TLS 1.3 握手 (1-RTT) ClientHello + 密钥协商参数 ServerHello + 密钥协商参数 + Finished 客户端发送 Finished 安全通信开始 总计 1 次网络往返 0-RTT 模式:无需握手即可传输数据 去掉独立证书块

从这张图能直观看到差异:左边 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。内网渗透的第一步就是嗅探弱加密。