TLS 1.2 与 TLS 1.3 对比:握手流程、加密套件、性能、安全性差异详解
说实话,TLS 1.2 到 1.3 的升级,是我这几年在项目中感受最深的协议变化。不是那种修修补补的小改,而是直接把握手砍掉了一大半。今天咱们就掰开揉碎,从握手流程、加密套件、性能、安全性四个角度比比看。
握手流程:从 2-RTT 到 1-RTT(甚至 0-RTT)
TLS 1.2 的握手,我刚开始接触时觉得挺优雅的,但用久了就发现——太慢了。完整的握手要 2 个 RTT(往返时延),再加上证书链传输,首次连接动不动就几百毫秒。
核心差异:TLS 1.3 把握手压缩到 1 个 RTT;如果复用会话,还能做到 0-RTT(虽然有些安全顾虑,后面再说)。
你看看这张流程图就明白了——左边是 TLS 1.2,右边是 TLS 1.3,步骤数差了一倍还多。
我当年在升级一个高并发 API 网关时,就因为 TLS 1.2 的握手延迟,导致首字节时间飙到 300 毫秒。换到 1.3 后直接降到 100 毫秒以内。嗯,这就是 1-RTT 的威力。
加密套件:从“菜市场”到“精品店”
TLS 1.2 支持的加密套件多到让人头疼。我记得有一次排查一个兼容性问题,抓包看到客户端列了 20 多个套件,服务器挑了一个很冷门的,结果两边算法都支持,但证书密钥长度不匹配……那叫一个折腾。
| 方面 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 支持的套件数量 | 30+(包括带 CBC、RC4、3DES 的弱套件) | 5 个(全部是 AEAD) |
| 密钥交换 | RSA、DH、ECDH(可单独指定) | 仅 ECDHE 或 DHE(强制前向安全) |
| 对称加密 | AES-CBC、AES-GCM、ChaCha20-Poly1305 等 | 仅 AES-GCM 和 ChaCha20-Poly1305 |
| 认证与 MAC | HMAC-SHA1、HMAC-SHA256 等(可能分离) | AEAD 自带认证(合并) |
我的建议:如果你现在还在配 TLS 1.2,尽量只开 ECDHE + AES-GCM 或者 ChaCha20。其他的套件——尤其是 CBC——能关就关。我在生产环境见过 CBC 的 padding oracle 攻击,虽然要凑条件,但能不冒险就别冒。
性能:握手延迟、CPU 开销、连接复用
性能这块,我直接拿数据说话。
- 握手延迟:TLS 1.2 完整握手 2-RTT(约 50-100ms 网络延迟下就是 100-200ms),TLS 1.3 完整握手 1-RTT(减半)。复用会话时,1.3 可以 0-RTT,而 1.2 还需要 1-RTT 的 abbreviated handshake。
- CPU 开销:TLS 1.3 只允许 ECDHE 密钥交换(单次 DH 计算),而 1.2 里 RSA 密钥交换虽然计算少,但没前向安全。实际上 1.3 的 ECDHE 计算量比 1.2 混合算法要低,因为省掉了证书验证后的加解密协商。
- 连接复用:TLS 1.3 的 PSK(预共享密钥)让客户端可以带一个 ticket 直接发数据;1.2 的 session ticket 也需要一次往返交换。
我帮过一个游戏公司做优化,他们的玩家大量使用移动网络,延迟本来就高。切到 TLS 1.3 后,登录握手时间从 400ms 降到 180ms,玩家掉线率直接降了 30%。说白了,性能提升主要就是少跑一趟网络来回。
安全性:前向安全、降级攻击、协议硬化
安全性是我最想说的部分。TLS 1.3 在安全设计上几乎是重写的。
特别注意:TLS 1.3 移除了所有非 AEAD 的加密模式(比如 CBC、RC4、3DES)。同时也移除了 RSA 密钥交换——这个做法当初在标准化时争议很大,但我举双手赞成。RSA 密钥交换没有前向安全,私钥泄露后所有历史会话都能被解密。
具体差异我列了一张表:
| 安全特性 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 前向安全 | 可选(取决于使用的密钥交换算法) | 强制(所有密钥交换都是 DHE/ECDHE) |
| 降级保护 | 靠 ClientHello 中的版本字段,可被中间人篡改 | 用“supported_versions”扩展+密钥确认,不可降级 |
| 0-RTT 重放 | 不适用 | 存在重放风险,要求应用层使用幂等性或禁用 0-RTT |
| 证书压缩 | 不压缩,传输大证书链时占带宽 | 可选压缩,减少带宽消耗 |
| 压缩方法 | 支持压缩(有 CRIME 攻击风险) | 完全移除压缩 |
| 重新协商 | 支持(但存在安全漏洞) | 不支持(彻底移除) |
我这里要特别说一下降级保护。我曾经碰到过一个坑:客户端支持 TLS 1.3,但中间某个负载均衡器把握手版本改成 1.2 让它们降级。TLS 1.2 的版本协商是靠明文中的 version 字段,中间人可以直接改。1.3 的 supported_versions 扩展是在加密握手内部确认的,中间人篡改会被检测到。
避坑指南
最后分享几个我自己踩过的坑,希望能帮你少走弯路:
我曾经在升级到 TLS 1.3 后,发现某些 Android 4.x 设备的浏览器连不上。因为那些设备根本不支持 TLS 1.3。解决方案是配置降级回退策略——优先 1.3,如果不成功就试 1.2,但千万不要同时开 1.1 或 1.0。我一般只保留 1.2 和 1.3 两个版本。
0-RTT 的陷阱:虽然 0-RTT 很诱人,但它有重放攻击风险。如果你用的是 HTTP/2 或 HTTP/3,务必确保应用层是幂等的(比如 GET 请求)。我曾经在支付回调里用了 0-RTT,结果出现重复扣款的惨案……后来果断把 0-RTT 关了。
还有一点:TLS 1.3 的证书验证逻辑变了。1.2 里证书可以在 ChangeCipherSpec 之前发送,1.3 里证书是在 ServerHello 之后加密发送的。如果你自己写 TLS 解析库,这里的逻辑必须完全重写。
好了,关于 TLS 1.2 和 1.3 的对比,核心就这些。总结一句话:能用 1.3 就别用 1.2,除非你有一堆 legacy 设备硬撑着。