2014年,IETF TLS工作组收到了一份来自Eric Rescorla的提案。这份题为《draft-rescorla-tls13-new-flows》的文档开宗明义地提出了TLS 1.3的两大设计目标:减少往返次数、移除不安全特性。四年后,RFC 8446正式发布,TLS 1.3将握手延迟从2-RTT压缩到1-RTT,会话恢复场景更是达到了0-RTT。

这听起来像是简单的"少发一条消息",但背后的技术逻辑远比表面复杂。TLS 1.2为什么需要两轮往返?TLS 1.3凭什么能砍掉一轮?0-RTT真的是免费的午餐吗?

TLS 1.2握手的时序困局

TLS 1.2的完整握手流程如下:

Client                                               Server
ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
Application Data             <------->     Application Data

仔细观察这个流程,第一轮往返是ClientHello和ServerHello(含Certificate、ServerKeyExchange等)。客户端发出ClientHello后,必须等待服务器返回证书和密钥交换参数,才能计算出预备主密钥(Pre-Master Secret)。

这就是2-RTT的根本原因:密钥协商依赖于服务器证书

为什么客户端不能提前开始密钥协商?

在TLS 1.2的RSA密钥交换模式下,客户端生成预备主密钥,然后用服务器证书中的公钥加密后发送。这意味着客户端必须先收到服务器的证书,才知道用哪个公钥加密。

在TLS 1.2的(ECDHE)密钥交换模式下,服务器需要在ServerKeyExchange消息中发送其临时的Diffie-Hellman公钥。同样,客户端必须等待这个消息。

无论哪种模式,核心问题都是一样的:客户端缺少开始密钥协商所需的信息。这些信息握在服务器手里,客户端必须先"问"一轮,服务器"答"一轮,双方才能开始真正的密钥计算。

TLS 1.3的核心突破:乐观预判

TLS 1.3的设计哲学发生了根本转变。Eric Rescorla在"The Road to TLS 1.3"演讲中指出:TLS 1.2假设客户端对服务器一无所知,第一轮往返主要用于"学习"服务器能力。但TLS 1.3大幅缩小了可选项范围——只支持(ECDHE)密钥交换,只允许有限的椭圆曲线。这意味着客户端可以"猜"服务器会接受什么参数

key_share扩展:第一轮往返就完成密钥交换

TLS 1.3引入了key_share扩展。客户端在ClientHello中直接包含自己的Diffie-Hellman公钥:

ClientHello {
    ...
    key_share: {
        named_group: x25519
        key_exchange: <client's ECDH public key>
    }
}

服务器收到ClientHello后,如果支持客户端指定的曲线(如X25519),直接生成自己的临时密钥对,在ServerHello中返回公钥:

ServerHello {
    ...
    key_share: {
        named_group: x25519
        key_exchange: <server's ECDH public key>
    }
}

此时,双方各自拥有了对方的公钥和自己的私钥,可以独立计算出共享密钥。密钥交换在第一轮往返中就完成了。

为什么这比TLS 1.2更安全?

在TLS 1.2中,服务器证书是明文传输的。TLS 1.3做了一个关键改变:ServerHello之后的所有消息都加密传输,包括服务器的证书。这是因为密钥交换已经完成,双方已经派生出了握手加密密钥。

这不仅减少了延迟,还提升了隐私性——被动攻击者无法看到服务器证书的具体内容。

从1-RTT到0-RTT:用空间换时间

TLS 1.3的0-RTT(Zero Round Trip Time)机制让会话恢复场景达到零往返延迟。其核心思想是:如果客户端和服务器曾经建立过连接,服务器会发给客户端一个会话票据(Session Ticket),其中包含一个预共享密钥(PSK)。下次连接时,客户端可以直接用这个PSK加密数据,随ClientHello一起发送。

ClientHello + early_data + pre_shared_key + key_share*
(Application Data*)                -------->
ServerHello + pre_shared_key
{EncryptedExtensions}
{Finished}                         <--------
{Finished}                         -------->
[Application Data]                 <-------> [Application Data]

0-RTT的安全代价

0-RTT不是免费的午餐。RFC 8446明确警告:0-RTT数据不提供前向安全性,且容易受到重放攻击。

重放攻击的场景是这样的:攻击者截获客户端的0-RTT数据包,然后多次发送给服务器。由于服务器无法区分这是新的请求还是重放的,可能会重复执行某些操作——比如重复扣款、重复发货。

Cloudflare在部署0-RTT时采取了极其保守的策略:只响应没有查询参数的GET请求,并添加了Cf-0rtt-Unique头部帮助源站识别重放。

被移除的特性:为性能和安全做减法

TLS 1.3不只做了加法,更做了大量减法。以下特性被彻底移除:

静态RSA密钥交换

TLS 1.2允许服务器直接用证书中的RSA公钥加密预备主密钥。这种方式不支持前向安全性——如果服务器的私钥泄露,历史所有会话都可以被解密。

TLS 1.3强制所有连接都使用临时Diffie-Hellman密钥交换,实现了强制前向安全性。

压缩

TLS压缩曾导致CRIME攻击。攻击者可以通过观察压缩后的密文长度变化,逐步推断出敏感信息(如会话Cookie)。TLS 1.3直接移除了压缩功能。

自定义Diffie-Hellman参数

TLS 1.2允许服务器指定任意的Diffie-Hellman参数。这导致了Logjam攻击——攻击者可以强制使用弱参数,从而破解密钥交换。TLS 1.3只允许预定义的安全曲线(如X25519、P-256、P-384)。

重新协商

TLS 1.2支持在已有连接上重新协商安全参数。这个功能导致了Triple Handshake攻击等安全问题。TLS 1.3移除了重新协商功能,代之以会话恢复和后握手认证机制。

性能数据:延迟降低的真实收益

根据学术论文《Analyzing SSL/TLS Handshake Latency in Modern Web Applications》的测试数据,TLS 1.3的平均握手延迟为57.4ms,而TLS 1.2为88.9ms,性能提升约35%。

在移动网络环境下,收益更加明显。一个RTT在3G网络下可能高达100-200ms。TLS 1.3省掉一个RTT,相当于节省了一个完整"往返"的时间。

根据Cloudflare的统计数据,约40%的HTTPS连接是会话恢复。对于这部分连接,0-RTT可以带来显著的性能提升——首字节时间(TTFB)可降低约20%。

中间件的代价

TLS 1.3的部署并非一帆风顺。Eric Rescorla在演讲中提到一个尴尬的现实:一些网络中间件(防火墙、入侵检测系统等)会解析TLS握手内容。当它们看到不认识的TLS 1.3消息格式时,会选择丢弃连接。

Firefox在测试中发现,TLS 1.3的连接错误率为3.9%,而TLS 1.2只有2.2%。解决方案是让TLS 1.3"伪装"成TLS 1.2——在关键位置插入一个空的ChangeCipherSpec消息,让中间件以为这是旧的协议格式。

这被称为"兼容性模式"(Compatibility Mode),RFC 8446的附录D.4详细描述了这个妥协方案。

设计启示

TLS 1.3的演进过程提供了几个值得深思的设计启示:

乐观预判优于保守等待:TLS 1.3假设客户端能猜中服务器支持的参数,把密钥交换提前。这种"乐观"的设计在现代网络环境中往往是正确的选择——服务器配置趋向标准化,客户端可以维护高质量的安全参数列表。

强制安全优于可选安全:TLS 1.2中前向安全性是可选的,TLS 1.3强制要求。历史证明,当安全成为可选项时,配置错误和中间人攻击就会乘虚而入。

做减法比做加法更难:移除RSA密钥交换、移除压缩、移除自定义参数,每一个决定都面临向后兼容性的挑战。但正是这些减法,让TLS 1.3成为了"默认安全"的协议。

理论分析与工程妥协并存:TLS 1.3是第一个与密码学界深度合作设计的TLS版本。但即使如此,中间件兼容性、0-RTT重放等问题仍然需要在协议层面做出妥协。

结语

从TLS 1.2的2-RTT到TLS 1.3的1-RTT,看似只是"省掉一轮往返",实则是密码学设计哲学的深刻变革。客户端不再等待服务器"告诉"自己该用什么参数,而是主动"推测"并提前行动。这种从被动响应到主动预判的转变,是现代协议设计的重要趋势。

至于0-RTT,它是对重复访问场景的优化,但重放攻击的风险意味着它不能滥用。安全与性能的权衡,永远是协议设计的核心命题。


参考资料

  1. Rescorla, E. (2018). RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3. IETF.
  2. Rescorla, E. (2018). The Road to TLS 1.3. IACR Cryptography Conference.
  3. Dowling, B. (2020). A Cryptographic Analysis of the TLS 1.3 Handshake Protocol. Journal of Cryptology.
  4. Cloudflare Blog. (2017). Introducing Zero Round Trip Time Resumption (0-RTT).
  5. Hasan, M.M. et al. (2025). Analyzing SSL/TLS Handshake Latency in Modern Web Applications. JISIS.
  6. Halfrost. (2019). HTTPS温故知新——直观感受TLS握手流程.
  7. The Illustrated TLS 1.2 Connection. https://tls12.xargs.org/
  8. The Illustrated TLS 1.3 Connection. https://tls13.xargs.org/