TLS 1.2与TLS 1.3差异归纳总结
这几年做Tokenization接口的加密对接,我发现一个挺有意思的现象。很多团队还在用TLS 1.2,问起来就是“稳定”。但你想想看,TLS 1.3都出来五年了,握手快、安全性高,为啥不换?说白了,就是不知道差异到底有多大。我最早在2019年给一个支付SDK升级TLS时,也犹豫过——直到我调了一次1.3的握手日志,才真的被惊艳到。今天咱们好好捋一捋这两种版本到底差在哪。
握手流程对比
握手环节是最大的变化。TLS 1.2完整握手需要两次往返(2-RTT),而TLS 1.3只要一次(1-RTT),还支持0-RTT模式。我做性能压测时,1.3的首次连接延迟比1.2低了近40%。下面这张图能看得很清楚:
密码套件与算法差异
TLS 1.2里面乱七八糟的密码套件太多了。我记得有个项目检查配置时发现团队还在用TLS_RSA_WITH_AES_128_CBC_SHA,这玩意在1.3里早被扔进历史垃圾桶了。TLS 1.3直接砍掉了RSA密钥交换、静态DH、CBC模式、RC4、3DES等等不安全的算法,只保留AEAD加密。下面这个表是我自己整理的核心差异:
| 项目 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 已认证密钥交换 | RSA, DHE, ECDHE | 仅 (EC)DHE(前向保密必须) |
| 加密算法 | AES-CBC, AES-GCM, ChaCha20, 3DES, RC4 | 仅AEAD: AES-128/256-GCM, ChaCha20-Poly1305 |
| 哈希算法 | SHA-1, SHA-256, SHA-384, MD5 | SHA-256, SHA-384 (禁止SHA-1) |
| 签名算法 | RSA, DSA, ECDSA | RSA (PSS), ECDSA, EdDSA |
| 会话恢复 | Session ID / Session Ticket | PSK + 0-RTT / Ticket |
安全性改进细节
其实TLS 1.3最大的安全性提升不是加了什么,而是砍了太多。比如:
- 移除了RSA密钥交换——RSA不支持前向保密,一旦私钥泄露,之前所有会话都能被解密。1.3强制使用(EC)DHE,每次会话独立临时密钥。
- 禁止CBC模式——Padding Oracle攻击在CBC模式下屡禁不止,换成AEAD后这些攻击直接失效。
- 握手消息加密——1.3在ServerHello后就立刻加密,证书和Finished都处于密文状态,中间人看不到服务器身份信息。
我记得当初做金融接口评审时,对方安全团队专门问了前向保密的问题。因为Tokenization接口如果泄露历史令牌,影响面太大。TLS 1.3的(EC)DHE恰好解决了这个痛点。
性能优化对比
除了握手少一个RTT,TLS 1.3在会话恢复上也比1.2快不少。1.2的Session Ticket需要服务端维护状态,而1.3的PSK (Pre-Shared Key)可以直接放在客户端。我测试过一个场景:
- 首次连接:1.3比1.2快约40%(1-RTT vs 2-RTT)
- 会话恢复(0-RTT):1.3可以做到零往返,直接发送加密数据。不过要注意,0-RTT有重放风险,Tokenization接口如果是幂等的,大胆用;否则最好只用于非敏感数据的预发送。
- CPU负载:1.3因为少了签名验证和密钥交换计算,服务端吞吐量提升了约10-20%。在线程数高的环境下,差别挺明显。
配置实战建议
如果你现在负责一个Tokenization接口的TLS配置,我的建议是:直接上TLS 1.3。但如果要兼容老客户端(比如某些IoT设备),可以保留1.2作为fallback。注意以下几点:
- 服务端优先协商1.3——Nginx里配置
ssl_protocols TLSv1.2 TLSv1.3;,让客户端先尝试1.3。 - 禁用不安全套件——TLS 1.2只保留
ECDHE-RSA-AES128-GCM-SHA256和ECDHE-RSA-AES256-GCM-SHA384,其余全关。 - 开启0-RTT但限制重放——如果接口允许幂等,用
ssl_early_data on;,但记得在应用层做去重(比如用单号或时间戳)。 - 证书签名要用PSS——1.3签名算法推荐RSA-PSS或ECDSA,不要用旧的PKCS#1 v1.5。
一个小坑:
我曾经在一个项目里开了TLS 1.3 + 0-RTT,但Tokenization接口的数据库操作不是幂等的,结果并发时重复提交了两次订单。原因是0-RTT重放了同一个请求。后来我们在Nginx加了一层ssl_early_data_replay_protection,同时在业务层用唯一请求ID做幂等校验才算解决。
总结一下:TLS 1.3不是小修小补,而是从设计上就砍掉了历史包袱。对于Tokenization接口,我更推荐直接用1.3。如果一个客户端连1.3都不支持,那它的安全性也堪忧——你想想看,连OpenSSL 1.1.1都五年前的东西了。别犹豫,该升就升。