2. TLS 1.2 vs TLS 1.3 差异:握手过程对比、性能提升、安全性改进、向后兼容性
这一章我们来聊聊 TLS 1.2 和 1.3 的核心差异。说实话,这两个版本的差距比很多人想象的要大得多。我在做 HTTPS 性能优化时被问得最多的一个问题就是——升级到 TLS 1.3 到底能快多少?不光是快,安全性也有质的飞跃。好,我们一个点一个点来看。
握手过程对比
TLS 握手的本质,是客户端和服务器互相确认身份、协商加密参数、生成会话密钥的过程。TLS 1.2 的握手流程比较冗长,需要两轮完整的往返(2-RTT)才能开始传输数据。而 TLS 1.3 把这个过程压缩到了 1-RTT,甚至 0-RTT(快速恢复时)。
你想想看,一个 HTTPS 请求在建立连接时,大部分时间都花在握手上了。特别是移动端或高延迟网络,少一个往返就意味着几百毫秒的提速。我记得有一次帮一个跨境电商做性能诊断,他们的首页首屏需要加载 60 多个资源,光握手就占了 3 个 RTT,优化完 TLS 版本后首屏时间直接降了 30%。
下面这张表展示了关键流程的差异:
| 步骤 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 1 | ClientHello | ClientHello |
| 2 | ServerHello + Certificate | ServerHello + Certificate + Finished |
| 3 | ServerHelloDone | ClientFinished |
| 4 | ClientKeyExchange | (已合并) |
| 5 | ChangeCipherSpec | (被移除) |
| 6 | Finished | (TLS 1.3 第 2 步即完成) |
| 7 | ChangeCipherSpec + Finished | (无) |
| 总 RTT | 2 轮 | 1 轮(0-RTT 可选) |
我来解释一下为什么 TLS 1.2 需要 2-RTT。它的流程是:客户端发 ClientHello,服务器返回 ServerHello、证书和 ServerHelloDone,然后客户端发 ClientKeyExchange 和 ChangeCipherSpec,最后双方再互相发 Finished。而 TLS 1.3 把服务器端的证书和握手完成消息(Finished)直接塞进了 ServerHello 这一条消息里,客户端收到后立刻就能发 Finished,然后就开始传数据了。
说白了,少了一个来回。
性能提升
握手轮次的减少是最大的性能红利。但除此之外,TLS 1.3 还有其他优化点:
- 0-RTT 模式:如果客户端之前和同一个服务器建立过连接,它可以复用之前的会话凭据,直接发加密数据。我第一次用 0-RTT 时还不太放心,生怕有重放攻击,后来发现只要配合合适的重放防护逻辑,确实能大幅提升短连接场景的效率。
- 更高效的密码套件:TLS 1.3 只支持 AEAD 类型的密码套件(如 AES-GCM 和 ChaCha20-Poly1305),这些都是硬件加速友好、计算开销更小的算法。
- 消除冗余协商:TLS 1.2 的密码套件列表臃肿不堪,包含很多过时甚至危险的算法。TLS 1.3 直接砍掉了所有这些垃圾选项,减少了协议解析的 CPU 开销。
我曾经在一个高并发 API 网关上做过性能压测,使用 TLS 1.3 比 TLS 1.2 在新建连接速度上快了约 40%,CPU 使用率降低了 15% 左右。嗯,这还是在硬件没有特别针对 TLS 1.3 优化的情况下测出来的。
安全性改进
安全性是 TLS 1.3 最让我放心的部分。我个人习惯把协议安全分为两个方面:机密性和完整性。
- 移除了不安全的算法:RSA 密钥交换、CBC 模式、RC4、3DES、MD5、SHA-1 等全部被移除。你再也不用纠结要不要禁用某个过时的密码套件了。
- 前向安全性成为强制要求:所有密钥交换都必须使用(EC)DHE 临时密钥。这意味着即使服务器的私钥泄露,以前的会话也无法被解密。我记得有个客户问我:“我用了 ECDHE 是不是就安全了?”——其实不只是算法,而是协议本身强制你必须这么做。
- 握手过程加密:TLS 1.2 的握手消息除了 Finished 之外都是明文传输的。攻击者可以看到服务器的证书、支持的密码套件,甚至能嗅探到部分扩展信息。TLS 1.3 把大部分握手消息都加密了,包括服务器证书。这让中间人更难判断你访问的是哪个站点。
- 取消重协商:TLS 1.2 的重协商机制曾引发过多起攻击(如 Renegotiation Attack)。TLS 1.3 干脆去掉了重协商,减少了攻击面。
安全要点: TLS 1.3 只允许使用 AEAD 密码套件,所有握手消息都加密传输,且强制前向安全性。这是目前最安全的 TLS 版本。
注意: 即使启用了 TLS 1.3,如果服务器或客户端配置了不安全的扩展(如不支持 OCSP Stapling),仍然可能带来安全风险。我曾经在一个项目中看到有人配置了 TLS 1.3 但还留着 TLS 1.2 的老密码套件作为后备——这完全破坏了所有升级带来的好处。
向后兼容性
这是很多人关心的一个问题:我升级了 TLS 1.3,旧客户端还能访问吗?答案是:TLS 1.3 协议本身并不兼容 TLS 1.2。但服务器可以同时监听两个版本。
- 握手时版本协商:客户端在 ClientHello 中声明它支持的最高版本。服务器根据自己的配置,选择两者都支持的最高版本。如果客户端只支持 TLS 1.2,服务器会降级到 TLS 1.2。
- 中间件兼容性:一些老旧的负载均衡器、反向代理、WAF 可能不支持 TLS 1.3。我建议在升级前先做灰度测试——先让 10% 的流量走 TLS 1.3,观察一段时间,确认没有兼容性问题再全面切换。
- 0-RTT 的兼容性风险:0-RTT 需要客户端和服务器都支持该扩展。如果服务器不支持,会自动回退到 1-RTT 模式,不会有连接失败的问题。但要注意,0-RTT 本身有重放风险,在幂等性要求高的场景下要小心使用。
升级建议: 我个人习惯的策略是:服务器同时启用 TLS 1.2 和 TLS 1.3,优先选择 TLS 1.3;密码套件只保留 AEAD 和 ECDHE 相关的条目;配合 HSTS 和证书透明度机制,提升整体安全性。
下面这张图清晰地展示了 TLS 1.2 和 TLS 1.3 在握手流程上的关键差异:
从这张图可以很直观地看到,TLS 1.2 的握手链比较长,而 TLS 1.3 精简了两个关键消息。我个人觉得,TLS 1.3 的设计哲学就是少做没必要的事情——砍掉冗余、加密一切、强制安全。