TLS 1.2 与 TLS 1.3 对比:主要区别、性能提升与安全性改进

聊到 TLS 协议升级,很多人第一个问题就是:“TLS 1.3 到底比 1.2 强在哪?”

我个人的习惯是,不急着列特性列表,先看一次真实的握手过程。你想想看,一次 HTTPS 连接,用户等那几百毫秒,很大一部分都耗在握手上了。TLS 1.3 的核心变化,说白了就是把手握从“两次往返”砍成“一次往返”。

我在好几个产线升级项目里都遇到过这种情况:业务方说“我们用了 CDN 也没用,用户首屏还是慢”。抓包一看,哦,TLS 1.2 握手占了 3 个 RTT(加上 TCP)。换成 1.3 之后,直接省掉一个 RTT,体验立竿见影。

一句话总结:TLS 1.3 用更少的握手步数、更强的密码原语、更干净的协议设计,实现了比 1.2 更快的连接和更高的安全底线。

握手流程:从 2-RTT 到 1-RTT(甚至 0-RTT)

TLS 1.2 的握手,差不多是这么个流程:

  1. ClientHello(客户端打招呼,带上支持的密码套件列表)
  2. ServerHello + Certificate + ServerKeyExchange + CertificateRequest(可选)
  3. ClientKeyExchange + ChangeCipherSpec + Finished
  4. ChangeCipherSpec + Finished

你看,这里至少有两次完整的网络往返。如果加上 TCP 的三次握手,用户等得心焦。

TLS 1.3 把步骤压缩了。它在 ClientHello 里直接带上密钥交换的参数(KeyShare),服务器收到后马上就能算出 premaster secret,一次往返就搞定。连 ChangeCipherSpec 这种历史包袱都基本砍掉了。

我踩过的坑:曾经在一个嵌入式设备上做 TLS 1.3 升级,底层硬件不支持 x25519 曲线。结果 ClientHello 里只带了 P-256 的 KeyShare,服务器选择困难,最后降级成 1.2 握手。白高兴一场。所以做 1.3 迁移时,一定要先确认硬件能跑哪些椭圆曲线。

性能提升:不止是省一个 RTT

除了握手轮次减少,TLS 1.3 还在几个关键地方做了优化:

  • 对称加密只用 AEAD:不再支持 CBC 模式,省掉了 MAC-then-encrypt 的 Padding Oracle 风险,计算量也更小。
  • 会话恢复更高效:PSK(预共享密钥)机制可以做到 0-RTT 恢复,后端用户几乎无感知地再次建立安全连接。
  • 证书压缩:服务器可以压缩证书链,减少传输大小,尤其对大证书链场景友好。

我在一个物联网网关项目里对比过:同样的硬件,TLS 1.2 完整握手要 80ms,TLS 1.3 一次握手只要 45ms,而且 0-RTT 恢复时直接降到 5ms。这差距,业务方看了直接点头。

安全性改进:砍掉了哪些“坏孩子”?

TLS 1.3 最激进的改动,是删掉了一大堆不安全的密码套件和扩展。我列个表,你就明白了:

协议版本 支持的密码套件(举例) TLS 1.3 状态
TLS 1.2 TLS_RSA_WITH_AES_128_CBC_SHA 已废弃(CBC + RSA 易受攻击)
TLS 1.2 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 已废弃(DSS 签名算法太弱)
TLS 1.2 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 保留(但 1.3 改用 HKDF 推导密钥)
TLS 1.3 TLS_AES_128_GCM_SHA256 强制支持(仅 AEAD + HKDF)
TLS 1.3 TLS_CHACHA20_POLY1305_SHA256 推荐支持(移动端友好)

你仔细看,TLS 1.3 的密码套件不再写死密钥交换算法和签名算法。它把这两部分抽成了独立扩展(supported_groups、signature_algorithms、key_share)。这样一来,服务端可以灵活选择「ECDHE + 某个曲线」以及「签名算法」,互不耦合。底层的密钥派生也换成了 HKDF,比之前基于 PRF 的设计更安全。

注意:曾经有团队在 TLS 1.3 里强行配置了 RSA 密钥交换(密码套件里还有 RSA),结果握手直接失败。因为 1.3 根本不支持 RSA 作为密钥交换算法,只支持 ECDHE 或 PSK。这个坑我亲眼见过两次。

SVG:TLS 1.2 vs TLS 1.3 握手流程对比

下面的图可以帮你直观看到握手步数的差异:

TLS 1.2 与 TLS 1.3 握手流程对比 TLS 1.2 握手(2-RTT) Client Server ClientHello ServerHello + Cert + KeyExchange ClientKeyExchange ChangeCipherSpec ChangeCipherSpec + Finished Finished 总共至少 2 个 RTT(不含 TCP) 支持 1.2 以下版本降级协商 TLS 1.3 握手(1-RTT) Client Server ClientHello + KeyShare ServerHello + Cert + KeyShare + Finished Finished + 应用数据 仅需 1 个 RTT 支持 0-RTT(PSK 恢复) 关键变化 • 移除 ChangeCipherSpec 消息,握手更简洁 • 密钥协商在 ClientHello 时就携带,服务端可以立即回复 Finished • 不支持 RSA 密钥交换,仅依赖 ECDHE 或 PSK

密码套件的变化:从“杂货铺”到“精品店”

TLS 1.2 的密码套件列表,我数过,RFC 里定义了上百个。很多管理者根本搞不清哪些安全,就一股脑全开着。结果就是 Logjam、Sweet32、ROBOT 这些攻击一个个找上门。

TLS 1.3 只保留了 5 个套件,全是 AEAD 加密 + HKDF 密钥派生。你必须选一个:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_CCM_SHA256
  • TLS_AES_128_CCM_8_SHA256(限制使用)

实际上,大多数场景只需要前两个。Chacha20 在移动端有硬件加速,性能更好。

我的建议:如果你还在维护 TLS 1.2 栈,先把 CBC 模式的套件关掉,强制用 GCM。然后逐步向 1.3 迁移。别想着一步到位,但也不能拖——Chrome 已经计划在 2025 年标记 TLS 1.2 为“不推荐”了。

降级防护:避免中间人搞鬼

一个容易忽略的点:TLS 1.3 加强了降级保护。它通过 ServerHello 中的特定随机字节(TLS 1.3 版本号字段的特定模式)来标记版本,服务器如果被强制降级到 1.2,客户端会检测到异常并终止连接。

我在一个运营商项目中遇到过这种情况:中间设备为了做流量审计,强行把 TLS 版本降成 1.0,结果客户端直接报了“protocol_version”错误。因为 1.3 客户端根本不允许低于 1.2 的版本出现。

一个小技巧:你可以用 openssl s_client -tls1_3 命令测试对端是否支持 1.3,然后用 -tls1_2 对比握手时间。我经常用这个方法给客户做“性能速评”。

好了,TLS 1.2 和 1.3 的核心差别就是这些。说白了,1.3 把协议设计得更干净、更快、更安全。如果你现在还在用 1.2,没有特别的历史原因,我建议你尽快规划升级路线。