第3章 TLS 1.3与TLS 1.2的区别

说实话,我刚接触TLS 1.3的时候,心里是有点抵触的。毕竟TLS 1.2用得好好的,改它干嘛?但等我真正去捋了一遍协议细节,才发现——嗯,这一版改动实在是太大了。大到什么程度呢?大到我建议你直接忘掉1.2的手绘脑图,重新画一张。

这一章我就带你逐个拆解,看看TLS 1.3到底比1.2强在哪。

握手流程:从2-RTT减到1-RTT

最直观的区别,就是握手次数。1.2需要两次完整往返(2-RTT)才能生成主密钥,而1.3只需要一次(1-RTT)。

阶段TLS 1.2TLS 1.3
初始握手2-RTT(ClientHello + ServerHello + Certificate + ServerHelloDone → ClientKeyExchange + Finished → ServerFinished)1-RTT(ClientHello + ServerHello + EncryptedExtensions + Certificate + Finished)
密钥交换中间人协商后走ChangeCipherSpecServerHello后直接发送加密扩展
证书传输明文传输加密后再传(部分场景)

我早期在做嵌入式SDK适配时,就被1.2那个又臭又长的握手流程折腾过。每次抓包都要看一堆ChangeCipherSpec,特别容易眼花。1.3把这些冗余全砍了——说白了,能提前算的密钥,在第一个Hello里就定下来。

一个小技巧:抓包时如果看到TLS 1.3的ClientHello里带了`key_share`扩展,那说明客户端已经在第一次消息里把秘钥协商参数传过去了。这也是握手能省掉一次往返的根本原因。

密码套件:从几十种砍到5种

1.2支持超过30种密码套件,什么AES-CBC、RC4、3DES……说实话,我见过不少老项目还在用RC4。但1.3做了个大手术:只允许AEAD加密算法。

  • TLS 1.2时代:密码套件名长到让人崩溃(比如 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384)
  • TLS 1.3时代:就5种,全部强制AEAD + 完美前向安全
TLS 1.3 官方密码套件说明
TLS_AES_128_GCM_SHA256最常用,性能好
TLS_AES_256_GCM_SHA384更高安全级别
TLS_CHACHA20_POLY1305_SHA256移动端、无AES硬件加速时推荐
TLS_AES_128_CCM_SHA256IoT场景优化
TLS_AES_128_CCM_8_SHA256短标签模式(不推荐日常使用)

我当时在验证一个SDK版本时,就因为1.3的密码套件列表长得太整齐而怀疑人生——真的只有5个?后来翻RFC发现确实如此。这种"少即是多"的设计,让配置和管理变得简单太多。

重要原则:TLS 1.3不再支持密钥传输协议(RSA-KEM),所有密钥交换都必须使用ECDHE或DHE。这意味着服务器无法提前知道客户端的公钥——也正因为这个改动,前向安全性才得以保证。

向前安全性:从"可选"变成"必须"

你想想看,如果一个攻击者今天把你的会话流量全部录下来,等过几年你私钥泄露了,还能不能解密这些流量?在TLS 1.2里,如果用了静态RSA密钥交换(也就是常见的 TLS_RSA_WITH_AES_128_CBC_SHA),那肯定能。但1.3彻底禁用了这种模式。

我记得有一次做客户代码审计,对方还在用 TLS_RSA_WITH_AES_256_CBC_SHA。我跟他说,你这个连接虽然用了强加密,但只要私钥一泄露,历史的会话都会被翻出来。他当时脸色就变了。所以向前安全(PFS)在1.3里是强制的,所有密钥交换都基于临时密钥对。

会话恢复:0-RTT的新玩法

1.2也有会话恢复——通过Session ID或Session Ticket。但1.3引入了一个更激进的东西:PSK(预共享密钥)+ 0-RTT。什么意思?就是第一次握手之后,客户端可以缓存一个密钥,下次再连的时候,直接在第一个消息里带上加密数据。

注意:0-RTT有重放攻击风险。我在一个支付SDK里就踩过坑——客户端用0-RTT重发了扣款请求,服务器没做去重,导致用户被重复扣款。后来我们强制对幂等性敏感的操作走完整1-RTT握手。

不过话说回来,在大多数Web场景下(比如API调用、实时通信),0-RTT能带来明显的延迟改善。如果你在适配SDK时发现某些场景握手时间特别长,不妨看看是不是会话票证没存好。

移除的安全隐患

1.3不光做了加法,还做了大量减法。下面是我列出来的几个被剔除的"经典坑":

  • 压缩功能:CRIME攻击的温床,直接移除
  • 静态RSA密钥交换:不提供前向安全,砍掉
  • ChangeCipherSpec:过去很多降级攻击都靠这个协议字段作妖
  • 不安全的哈希:MD5、SHA-1在证书签名里还能用,但在握手MAC中被禁用
  • ECCP曲线:只保留P-256、P-384、P-521、X25519、X448(去掉了P-224、secp256k1等)

我曾经在解析1.2的ChangeCipherSpec时,因为时序问题搞错过一次——服务端发了两次CCS,客户端直接崩溃。1.3虽然还保留了这个消息的兼容形态,但实际流程里已经完全用不到了。

一张图看懂区别

TLS 1.2 vs TLS 1.3 握手流程对比 TLS 1.2(2-RTT) ClientHello ServerHello + Certificate + ServerHelloDone ClientKeyExchange + ChangeCipherSpec ServerFinished ClientFinished → 应用数据 TLS 1.3(1-RTT + 0-RTT) ClientHello (key_share, psk_key_exchange_modes) ServerHello + EncryptedExtensions + Certificate ServerFinished + 应用数据 (可选)0-RTT:ClientHello 直接带加密数据 完整握手完成(1-RTT)或 0-RTT 成功 TLS 1.3 砍掉了 ChangeCipherSpec、压缩、静态RSA,新增 PSK 与 0-RTT

核心差异总结:TLS 1.3 把原本需要两次往返的消息合并成一次,同时把所有不安全的内容全部切除。适配SDK时,你只需要关注密码套件列表、会话票证缓存、以及是否启用0-RTT这三点。