RFC 9001 使用 TLS 保护 QUIC 2021年5月
Thomson & Turner 标准轨道 [页]
流:
互联网工程任务组(IETF)
RFC:
9001
类别:
标准轨道
发布:
ISSN:
2070-1721
作者:
M. Thomson,
Mozilla
S. Turner,
sn3rd

RFC 9001

使用 TLS 保护 QUIC

摘要

本文档描述了如何使用传输层安全性(TLS)来保护 QUIC。

本备忘录状态

这是一份互联网标准轨道文档。

本文档是互联网工程任务组(IETF)的产物。它代表了 IETF 社区的共识。它已经接受公开审查,并已由互联网工程指导组 (IESG)批准发布。关于互联网标准的更多信息见 RFC 7841 第 2 节。

关于本文档当前状态、任何勘误以及如何提供反馈的信息,可在 https://www.rfc-editor.org/info/rfc9001 获取。

目录

1. 引言

本文档描述了如何使用 TLS [TLS13] 来保护 QUIC [QUIC-TRANSPORT]

TLS 1.3 为连接建立提供了相对于先前版本的关键延迟改进。 在没有丢包的情况下,大多数新连接可以在单个往返内建立并得到保护; 在同一客户端和服务器之间的后续连接中,客户端通常可以立即发送 应用数据,也就是说,使用零往返建立。

本文档描述了 TLS 如何作为 QUIC 的安全组件发挥作用。

2. 记法约定

本文档中的关键词 “MUST”、“MUST NOT”、 “REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、 “SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY” 和 “OPTIONAL”,当且仅当它们如这里所示以全大写形式出现时, 应按 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。

本文档使用 [QUIC-TRANSPORT] 中确立的术语。

为简洁起见,缩写 TLS 用于指代 TLS 1.3,不过也可以使用更新版本; 见 第 4.2 节

2.1. TLS 概述

TLS 为两个端点提供了一种在不可信介质(例如互联网)上建立 通信手段的方式。TLS 使对等方认证成为可能,并为端点交换的 消息提供机密性和完整性保护。

在内部,TLS 是一个分层协议,其结构如 图 1 所示。

          +-------------+------------+--------------+---------+
Content   |             |            |  Application |         |
Layer     |  Handshake  |   Alerts   |     Data     |   ...   |
          |             |            |              |         |
          +-------------+------------+--------------+---------+
Record    |                                                   |
Layer     |                      Records                      |
          |                                                   |
          +---------------------------------------------------+
图 1TLS 层

每个内容层消息(例如握手、警报和应用数据)都由记录层作为 一系列带类型的 TLS 记录承载。记录会分别受到密码学保护, 然后通过可靠传输(通常是 TCP)传输,该传输提供排序和保证交付。

TLS 认证密钥交换发生在两个端点之间:客户端和服务器。客户端发起交换, 服务器作出响应。如果密钥交换成功完成,客户端和服务器都会就一个机密达成一致。 TLS 同时支持预共享密钥(PSK)以及基于有限域或椭圆曲线的 Diffie-Hellman((EC)DHE)密钥交换。PSK 是 Early Data(0-RTT)的基础; 后者在 (EC)DHE 密钥被销毁时提供前向保密性(FS)。这两种模式也可以组合使用, 在使用 PSK 进行认证的同时提供前向保密性。

完成 TLS 握手后,客户端将得知并认证服务器的身份,而服务器也可以选择 得知并认证客户端的身份。TLS 支持对服务器和客户端使用基于 X.509 [RFC5280] 证书的认证。 当使用 PSK 密钥交换(如恢复中)时,对 PSK 的知晓可用于认证对等方。

TLS 密钥交换能够抵抗攻击者的篡改,并会产生不能由任一参与对等方控制的 共享机密。

TLS 提供两种 QUIC 关注的基本握手模式:

  • 完整的 1-RTT 握手,其中客户端能够在一个往返后 发送应用数据,而服务器在收到来自客户端的第一条握手消息后立即响应。
  • 0-RTT 握手,其中客户端使用它先前获知的关于服务器的信息 立即发送应用数据。攻击者可以重放这些应用数据,因此 0-RTT 不适合 承载那些在被重放时可能发起任何会导致不良影响的操作的指令。

带有 0-RTT 应用数据的简化 TLS 握手如 图 2 所示。

    Client                                             Server

    ClientHello
   (0-RTT Application Data)  -------->
                                                  ServerHello
                                         {EncryptedExtensions}
                                                    {Finished}
                             <--------      [Application Data]
   {Finished}                -------->

   [Application Data]        <------->      [Application Data]

    () Indicates messages protected by Early Data (0-RTT) Keys
    {} Indicates messages protected using Handshake Keys
    [] Indicates messages protected using Application Data
       (1-RTT) Keys
图 2带有 0-RTT 的 TLS 握手

图 2 省略了 EndOfEarlyData 消息,该消息在 QUIC 中不使用;见 第 8.3 节。同样,QUIC 既不使用 ChangeCipherSpec, 也不使用 KeyUpdate 消息。ChangeCipherSpec 在 TLS 1.3 中是冗余的;见 第 8.4 节。 QUIC 有自己的密钥更新机制;见 第 6 节

数据使用多个加密级别进行保护:

  • Initial 密钥
  • Early data(0-RTT)密钥
  • Handshake 密钥
  • Application data(1-RTT)密钥

应用数据只能出现在 early data 和 application data 级别中。 握手和警报消息可以出现在任何级别中。

如果客户端和服务器先前已经通信,则可以使用 0-RTT 握手。 在 1-RTT 握手中,客户端在收到服务器发送的所有握手消息之前, 无法发送受保护的应用数据。

3. 协议概述

QUIC [QUIC-TRANSPORT] 承担对数据包进行机密性和完整性保护的责任。为此,它使用从 TLS 握手 [TLS13] 派生的密钥,但并不(像使用 TCP 时那样)在 QUIC 上承载 TLS 记录,而是直接在 QUIC 传输中承载 TLS 握手和警报消息;QUIC 传输接管 TLS 记录层的职责,如 图 3 所示。

+--------------+--------------+ +-------------+
|     TLS      |     TLS      | |    QUIC     |
|  Handshake   |    Alerts    | | Applications|
|              |              | |  (h3, etc.) |
+--------------+--------------+-+-------------+
|                                             |
|                QUIC Transport               |
|   (streams, reliability, congestion, etc.)  |
|                                             |
+---------------------------------------------+
|                                             |
|            QUIC Packet Protection           |
|                                             |
+---------------------------------------------+
图 3QUIC 层

QUIC 还依赖 TLS 来进行认证,以及协商对安全和性能至关重要的参数。

这两个协议并非严格分层,而是彼此协作:QUIC 使用 TLS 握手;TLS 使用 QUIC 提供的可靠性、有序交付和记录层。

从高层看,TLS 组件和 QUIC 组件之间有两种主要交互:

图 4 更详细地展示了这些交互, 并特别标出了 QUIC 数据包保护。

+------------+                               +------------+
|            |<---- Handshake Messages ----->|            |
|            |<- Validate 0-RTT Parameters ->|            |
|            |<--------- 0-RTT Keys ---------|            |
|    QUIC    |<------- Handshake Keys -------|    TLS     |
|            |<--------- 1-RTT Keys ---------|            |
|            |<------- Handshake Done -------|            |
+------------+                               +------------+
 |         ^
 | Protect | Protected
 v         | Packet
+------------+
|   QUIC     |
|  Packet    |
| Protection |
+------------+
图 4QUIC 与 TLS 的交互

不同于 TCP 上的 TLS,想要发送数据的 QUIC 应用不会使用 TLS Application Data 记录来发送数据。相反,它们将数据作为 QUIC STREAM 帧或其他帧类型发送,然后这些帧被承载在 QUIC 数据包中。

4. 承载 TLS 消息

QUIC 在 CRYPTO 帧中承载 TLS 握手数据,每个 CRYPTO 帧由一段 以偏移和长度标识的连续握手数据块组成。这些帧被打包进 QUIC 数据包,并在当前加密级别下加密。与 TCP 上的 TLS 一样,一旦 TLS 握手数据已经交付给 QUIC,QUIC 就负责可靠地交付它。TLS 产生的 每个数据块都与 TLS 当前正在使用的一组密钥相关联。如果 QUIC 需要重传该数据,它 MUST 使用相同密钥, 即使 TLS 已经更新到更新的密钥。

每个加密级别对应一个数据包号空间。所使用的数据包号空间决定了 帧的语义。某些帧在不同的数据包号空间中被禁止;见 [QUIC-TRANSPORT] 的第 12.5 节

由于数据包可能在传输线上被重排序,QUIC 使用数据包类型来指示 给定数据包使用哪些密钥进行保护,如 表 1 所示。当需要发送不同类型的数据包时, 端点 SHOULD 使用合并数据包将它们发送在同一个 UDP 数据报中。

表 1按数据包类型划分的加密密钥
数据包类型 加密密钥 PN 空间
Initial Initial secrets Initial
0-RTT Protected 0-RTT Application data
Handshake Handshake Handshake
Retry Retry N/A
Version Negotiation N/A N/A
Short Header 1-RTT Application data

[QUIC-TRANSPORT] 的第 17 节 展示了各加密级别的数据包如何融入握手过程。

4.1. 到 TLS 的接口

图 4 所示,从 QUIC 到 TLS 的接口由四个主要功能组成:

  • 发送和接收握手消息
  • 处理来自已恢复会话的已存储传输和应用状态, 并确定生成或接受 0-RTT 数据是否有效
  • 重新换钥(发送和接收两者)
  • 更新握手状态

可能还需要其他功能来配置 TLS。特别是,QUIC 和 TLS 需要就 由哪一方负责验证对等方凭据达成一致,例如证书验证 [RFC5280]

4.1.1. 握手完成

在本文档中,当 TLS 栈报告握手完成时,TLS 握手即被认为完成。 这发生在 TLS 栈既已发送 Finished 消息,又已验证对等方的 Finished 消息时。 验证对等方的 Finished 消息使端点确信先前的握手消息未被修改。 注意,握手不会在两个端点同时完成。因此,任何基于握手完成的要求 都取决于相关端点的视角。

4.1.2. 握手已确认

在本文档中,当握手完成时,服务器处的 TLS 握手即被认为已确认。 服务器 MUST 在握手完成后立即发送 HANDSHAKE_DONE 帧。在客户端,当收到 HANDSHAKE_DONE 帧时, 握手被认为已确认。

此外,客户端 MAY 在收到对 1-RTT 数据包的确认时认为握手已确认。这可以通过记录使用 1-RTT 密钥发送的最低数据包号,并将其与任何收到的 1-RTT ACK 帧中的 Largest Acknowledged 字段进行比较来实现:一旦后者大于或等于前者, 握手即被确认。

4.1.3. 发送和接收握手消息

为了驱动握手,TLS 依赖于能够发送和接收握手消息。 此接口上有两个基本功能:一个是 QUIC 请求握手消息,另一个是 QUIC 提供组成握手消息的字节。

在开始握手之前,QUIC 向 TLS 提供它希望承载的传输参数 (见 第 8.2 节)。

QUIC 客户端通过向 TLS 请求 TLS 握手字节来启动 TLS。 客户端在发送其第一个数据包之前获取握手字节。QUIC 服务器通过向 TLS 提供客户端的握手字节来启动该过程。

在任意时刻,端点处的 TLS 栈都有一个当前发送加密级别和一个 当前接收加密级别。TLS 加密级别决定用于保护数据的 QUIC 数据包类型和密钥。

每个加密级别都关联不同的字节序列,该序列通过 CRYPTO 帧可靠地传输给对等方。当 TLS 提供要发送的握手字节时,它们会 追加到当前加密级别的握手字节中。随后加密级别决定承载所得 CRYPTO 帧的数据包类型;见 表 1

使用四个加密级别,为 Initial、0-RTT、Handshake 和 1-RTT 数据包生成密钥。CRYPTO 帧只在其中三个级别中承载,省略 0-RTT 级别。这四个级别对应三个数据包号空间:Initial 和 Handshake 加密数据包使用各自独立的空间;0-RTT 和 1-RTT 数据包使用 application data 数据包号空间。

QUIC 将 TLS 握手记录的未受保护内容作为 CRYPTO 帧的内容。 QUIC 不使用 TLS 记录保护。QUIC 将 CRYPTO 帧组装进 QUIC 数据包,这些数据包使用 QUIC 数据包保护进行保护。

QUIC CRYPTO 帧只承载 TLS 握手消息。TLS 警报会转换为 QUIC CONNECTION_CLOSE 错误码;见 第 4.8 节。 TLS 应用数据和其他内容类型不能由 QUIC 在任何加密级别承载; 如果从 TLS 栈收到这些内容,则为错误。

当端点从网络接收包含 CRYPTO 帧的 QUIC 数据包时, 它按如下方式处理:

  • 如果数据包使用当前 TLS 接收加密级别, 则照常将数据排序到输入流中。与 STREAM 帧一样,偏移用于找到 数据序列中的正确位置。如果此过程的结果是有新数据可用, 则按顺序将其交付给 TLS。
  • 如果数据包来自先前安装的加密级别, 它 MUST NOT 包含延伸到该流中先前已接收数据末尾之外的数据。实现 MUST 将任何违反此要求的情况视为 PROTOCOL_VIOLATION 类型的连接错误。
  • 如果数据包来自新的加密级别, 则保存以供 TLS 稍后处理。一旦 TLS 转为从此加密级别接收, 保存的数据即可提供给 TLS。当 TLS 为更高加密级别提供密钥时, 如果存在来自先前加密级别且 TLS 尚未消耗的数据,则这 MUST 被视为 PROTOCOL_VIOLATION 类型的连接错误。

每次向 TLS 提供新数据时,都会从 TLS 请求新的握手字节。 如果 TLS 已收到的握手消息不完整,或者没有数据可发送, TLS 可能不提供任何字节。

CRYPTO 帧的内容可以由 TLS 增量处理,也可以缓冲到完整消息或 消息群可用时再处理。TLS 负责缓冲已按顺序到达的握手字节。 QUIC 负责缓冲乱序到达的握手字节,或者缓冲尚未就绪的加密级别的 握手字节。QUIC 不为 CRYPTO 帧提供任何流量控制手段;见 [QUIC-TRANSPORT] 的第 7.5 节

一旦 TLS 握手完成,就会将此情况连同 TLS 需要发送的任何 最终握手字节一起通知 QUIC。在此阶段,对等方在握手期间通告的 传输参数已得到认证;见 第 8.2 节

握手完成后,TLS 变为被动状态。TLS 仍可从其对等方接收数据并 作出相应响应,但除非应用或 QUIC 特别请求,否则它不需要发送更多数据。 发送数据的一个原因是服务器可能希望向客户端提供额外的或更新的 会话票据。

握手完成后,QUIC 只需要向 TLS 提供到达 CRYPTO 流中的任何数据。 采用握手期间使用的相同方式,在提供收到的数据后向 TLS 请求新数据。

4.1.4. 加密级别变化

当给定加密级别的密钥对 TLS 可用时,TLS 会向 QUIC 指示 该加密级别的读取或写入密钥可用。

新密钥的可用性始终是向 TLS 提供输入的结果。TLS 只会在 (由客户端)初始化之后,或在提供了新的握手数据时提供新密钥。

不过,TLS 实现可能会异步执行其某些处理。尤其是, 验证证书的过程可能需要一些时间。在等待 TLS 处理完成期间, 如果收到的数据包可能会使用尚不可用的密钥进行处理,端点 SHOULD 对这些数据包进行缓冲。一旦 TLS 提供密钥,即可处理这些数据包。 端点 SHOULD 在此期间继续响应可以处理的数据包。

处理输入之后,TLS 可能会产生握手字节、新加密级别的密钥, 或两者都有。

当新的加密级别变得可用时,TLS 向 QUIC 提供三项内容:

  • 一个机密
  • 一个带关联数据的认证加密(AEAD)函数
  • 一个密钥派生函数(KDF)

这些值基于 TLS 协商的值,并由 QUIC 用于生成数据包和标头保护密钥; 见 第 5 节第 5.4 节

如果 0-RTT 可用,它在客户端发送 TLS ClientHello 消息后, 或服务器收到该消息后就绪。向 QUIC 客户端提供第一批握手字节后, TLS 栈可能会发出切换到 0-RTT 密钥的信号。在服务器端, 在收到包含 ClientHello 消息的握手字节后,TLS 服务器可能会发出 0-RTT 密钥可用的信号。

虽然 TLS 一次只使用一个加密级别,但 QUIC 可以使用多个级别。 例如,在发送其 Finished 消息(使用 Handshake 加密级别的 CRYPTO 帧)之后,端点可以发送 STREAM 数据(使用 1-RTT 加密)。 如果 Finished 消息丢失,端点会使用 Handshake 加密级别来重传 丢失的消息。数据包的重排序或丢失可能意味着 QUIC 需要处理多个 加密级别的数据包。在握手期间,这意味着可能要处理高于和低于 TLS 当前使用的加密级别的数据包。

特别是,服务器实现需要能够在读取 0-RTT 加密级别的数据包的 同时读取 Handshake 加密级别的数据包。客户端可能会将用 Handshake 密钥保护的 ACK 帧与 0-RTT 数据交错发送,而服务器需要处理这些确认, 以检测丢失的 Handshake 数据包。

QUIC 还需要访问某些密钥,而这些密钥通常可能不会提供给 TLS 实现。 例如,客户端可能需要在准备好以该加密级别发送 CRYPTO 帧之前 确认 Handshake 数据包。因此,TLS 需要在可能为自身使用产生这些密钥之前 将密钥提供给 QUIC。

4.1.5. TLS 接口摘要

图 5 总结了 客户端和服务器上 QUIC 与 TLS 之间的交换。实线箭头表示承载握手数据的 数据包;虚线箭头显示可以发送应用数据的位置。每个箭头都标注了 该传输使用的加密级别。

Client                                                    Server
======                                                    ======

Get Handshake
                     Initial ------------->
Install tx 0-RTT keys
                     0-RTT - - - - - - - ->

                                              Handshake Received
                                                   Get Handshake
                     <------------- Initial
                                           Install rx 0-RTT keys
                                          Install Handshake keys
                                                   Get Handshake
                     <----------- Handshake
                                           Install tx 1-RTT keys
                     <- - - - - - - - 1-RTT

Handshake Received (Initial)
Install Handshake keys
Handshake Received (Handshake)
Get Handshake
                     Handshake ----------->
Handshake Complete
Install 1-RTT keys
                     1-RTT - - - - - - - ->

                                              Handshake Received
                                              Handshake Complete
                                             Handshake Confirmed
                                           Install rx 1-RTT keys
                     <--------------- 1-RTT
                           (HANDSHAKE_DONE)
Handshake Confirmed
图 5QUIC 与 TLS 之间的交互摘要

图 5 将构成单个 “flight” 消息的多个数据包分别处理,以展示传入消息会触发哪些 不同操作。这显示了多个 “Get Handshake” 调用,用于在不同加密级别 获取握手消息。新的握手消息会在处理完传入数据包后请求。

图 5 展示了 一种简单握手交换的可能结构。确切过程会根据端点实现的结构以及 数据包到达的顺序而变化。实现可以使用不同数量的操作, 或以其他顺序执行它们。

4.2. TLS 版本

本文档描述了如何将 TLS 1.3 [TLS13] 与 QUIC 一起使用。

在实践中,TLS 握手会协商要使用的 TLS 版本。 如果两个端点都支持该版本,这可能导致协商出比 1.3 更新的 TLS 版本。 只要该更新版本支持 QUIC 所使用的 TLS 1.3 特性,这是可以接受的。

客户端 MUST NOT 提供早于 1.3 的 TLS 版本。 配置不当的 TLS 实现可能会协商 TLS 1.2 或其他更旧的 TLS 版本。 如果协商出早于 1.3 的 TLS 版本,端点 MUST 终止连接。

4.3. ClientHello 大小

来自客户端的第一个 Initial 数据包包含其第一条密码学握手消息的 开始部分或全部内容,对于 TLS 而言这就是 ClientHello。服务器可能需要 解析整个 ClientHello(例如,为了访问 Server Name Identification (SNI) 或 Application-Layer Protocol Negotiation (ALPN) 等扩展),以决定是否接受 新进入的 QUIC 连接。如果 ClientHello 跨越多个 Initial 数据包, 这类服务器将需要缓冲最先收到的片段;如果客户端地址尚未验证, 这可能消耗过多资源。为避免这种情况,服务器 MAY 使用 Retry 功能(见 [QUIC-TRANSPORT] 的第 8.1 节), 以便只缓冲来自地址已验证客户端的部分 ClientHello 消息。

QUIC 数据包和成帧会为 ClientHello 消息增加至少 36 字节的开销。 如果客户端选择的 Source Connection ID 字段长度大于零字节, 该开销还会增加。开销还不包括令牌或长于 8 字节的 Destination Connection ID, 如果服务器发送 Retry 数据包,这两者都可能是必需的。

典型的 TLS ClientHello 可以轻松放入一个 1200 字节的数据包中。 然而,除了 QUIC 增加的开销之外,还有多个变量可能导致超过此限制。 大型会话票据、多个或较大的密钥份额,以及很长的受支持密码套件、 签名算法、版本、QUIC 传输参数和其他可协商参数及扩展列表, 都可能使该消息增大。

对于服务器,除了连接 ID 和令牌之外,TLS 会话票据的大小也会影响 客户端高效连接的能力。最小化这些值的大小会增加客户端使用它们且仍能 将整个 ClientHello 消息放入其第一个 Initial 数据包中的可能性。

TLS 实现无需确保 ClientHello 足够大以满足 QUIC 对承载 Initial 数据包的数据报的要求;见 [QUIC-TRANSPORT] 的第 14.1 节。QUIC 实现使用 PADDING 帧或数据包合并来确保数据报足够大。

4.4. 对等方认证

认证要求取决于正在使用的应用协议。TLS 提供服务器认证, 并允许服务器请求客户端认证。

客户端 MUST 认证服务器的身份。 这通常涉及验证服务器的身份包含在证书中,并且该证书由受信实体签发 (例如见 [RFC2818])。

服务器 MAY 请求客户端在握手期间认证。 如果客户端在被请求时无法认证,服务器 MAY 拒绝连接。 客户端认证的要求因应用协议和部署而异。

服务器 MUST NOT 使用握手后客户端认证 (如 [TLS13] 的第 4.6.2 节 中所定义),因为 QUIC 提供的复用使客户端无法 将证书请求与触发它的应用级事件相关联(见 [HTTP2-TLS13])。更具体地说, 服务器 MUST NOT 发送握手后 TLS CertificateRequest 消息, 客户端 MUST 将收到此类消息视为 PROTOCOL_VIOLATION 类型的连接错误。

4.5. 会话恢复

QUIC 可以使用 TLS 1.3 的会话恢复功能。它通过在握手完成后 在 CRYPTO 帧中承载 NewSessionTicket 消息来实现这一点。会话恢复可用于 提供 0-RTT,也可在禁用 0-RTT 时使用。

使用会话恢复的端点在创建恢复连接时,可能需要记住关于当前连接的 某些信息。TLS 要求保留某些信息;见 [TLS13] 的第 4.6.1 节。除非还使用 0-RTT,否则 QUIC 本身不依赖于 恢复连接时保留的任何状态;见 [QUIC-TRANSPORT] 的第 7.4.1 节第 4.6.1 节。使用 QUIC 的应用协议可能依赖于 在恢复连接之间保留的状态。

客户端可以将恢复所需的任何状态与会话票据一起存储。 服务器可以使用会话票据来帮助承载状态。

会话恢复允许服务器将原始连接上的活动与恢复连接关联起来, 这对客户端而言可能是隐私问题。客户端可以选择不启用恢复, 以避免创建这种关联。客户端 SHOULD NOT 重用票据, 因为这会允许服务器之外的实体关联连接;见 [TLS13] 的附录 C.4

4.6. 0-RTT

QUIC 中的 0-RTT 功能允许客户端在握手完成之前发送应用数据。 这是通过复用先前连接中协商的参数实现的。为启用此功能,0-RTT 依赖客户端记住关键参数,并向服务器提供一个 TLS 会话票据, 该票据允许服务器恢复相同信息。

该信息包括决定 TLS 状态的参数(受 [TLS13] 管辖)、QUIC 传输参数、 所选择的应用协议,以及应用协议可能需要的任何信息;见 第 4.6.3 节。 此信息决定如何形成 0-RTT 数据包及其内容。

为确保两个端点都能获得相同信息,用于建立 0-RTT 的所有信息都来自 同一连接。端点不能选择性地忽略可能改变 0-RTT 发送或处理的信息。

[TLS13] 对原始连接与 任何尝试使用 0-RTT 之间的时间设定了七天的限制。0-RTT 使用还有其他约束, 尤其是由可能暴露于重放攻击所导致的约束;见 第 9.2 节

4.6.1. 启用 0-RTT

NewSessionTicket 消息中的 TLS early_data 扩展被定义为 (在 max_early_data_size 参数中)传达服务器愿意接受的 TLS 0-RTT 数据量。QUIC 不使用 TLS early data。QUIC 使用 0-RTT 数据包承载 early data。因此,max_early_data_size 参数被重新用作哨兵值 0xffffffff,表示服务器愿意接受 QUIC 0-RTT 数据。若要表示服务器 不接受 0-RTT 数据,则从 NewSessionTicket 中省略 early_data 扩展。 客户端可以在 QUIC 0-RTT 中发送的数据量由服务器提供的 initial_max_data 传输参数控制。

服务器 MUST NOT 发送 max_early_data_size 字段设置为 0xffffffff 之外任何值的 early_data 扩展。客户端 MUST 将收到包含 early_data 扩展且该扩展带有任何其他值的 NewSessionTicket 视为 PROTOCOL_VIOLATION 类型的连接错误。

希望发送 0-RTT 数据包的客户端会在后续握手的 ClientHello 消息中使用 early_data 扩展;见 [TLS13] 的第 4.2.10 节。 随后它在 0-RTT 数据包中发送应用数据。

如果服务器发送了 NEW_TOKEN 帧,尝试 0-RTT 的客户端也可以提供 地址验证令牌;见 [QUIC-TRANSPORT] 的第 8.1 节

4.6.2. 接受和拒绝 0-RTT

服务器通过在 EncryptedExtensions 中发送 early_data 扩展来 接受 0-RTT;见 [TLS13] 的第 4.2.10 节。随后服务器处理并确认 它收到的 0-RTT 数据包。

服务器通过发送不带 early_data 扩展的 EncryptedExtensions 来拒绝 0-RTT。如果服务器发送 TLS HelloRetryRequest,它总是会拒绝 0-RTT。 在拒绝 0-RTT 时,服务器 MUST NOT 处理任何 0-RTT 数据包,即使它能够处理。当 0-RTT 被拒绝时, 如果客户端能够检测到该条件,它 SHOULD 将收到对 0-RTT 数据包的确认 视为 PROTOCOL_VIOLATION 类型的连接错误。

当 0-RTT 被拒绝时,客户端所假定的所有连接特征都可能不正确。 这包括应用协议的选择、传输参数以及任何应用配置。因此,客户端 MUST 重置所有流的状态,包括绑定到这些流的应用状态。

如果客户端收到 Retry 或 Version Negotiation 数据包, 它 MAY 重新尝试 0-RTT。这些数据包并不表示 0-RTT 被拒绝。

4.6.3. 验证 0-RTT 配置

当服务器收到带有 early_data 扩展的 ClientHello 时, 它必须决定是否接受来自客户端的 0-RTT 数据。此决策的一部分由 TLS 栈作出(例如,检查正在恢复的密码套件是否包含在 ClientHello 中; 见 [TLS13] 的第 4.2.10 节)。即使 TLS 栈没有理由拒绝 0-RTT 数据,QUIC 栈或使用 QUIC 的应用协议也可能因为与恢复会话 关联的传输或应用配置与服务器当前配置不兼容而拒绝 0-RTT 数据。

QUIC 要求将额外的传输状态与 0-RTT 会话票据关联。 实现这一点的一种常见方式是使用无状态会话票据,并将此状态存储在 会话票据中。使用 QUIC 的应用协议在关联或存储状态方面可能有类似要求。 该关联状态用于决定是否必须拒绝 0-RTT 数据。例如,HTTP/3 设置 [QUIC-HTTP] 决定如何解释来自客户端的 0-RTT 数据。使用 QUIC 的其他应用可能 对确定是否接受或拒绝 0-RTT 数据有不同要求。

4.7. HelloRetryRequest

HelloRetryRequest 消息(见 [TLS13] 的第 4.1.4 节)可用于请求客户端提供新信息,例如密钥份额, 或用于验证客户端的某些特征。从 QUIC 的角度看,HelloRetryRequest 与 Initial 数据包中承载的其他密码学握手消息没有区别。尽管原则上 可以使用此功能进行地址验证,但 QUIC 实现 SHOULD 改用 Retry 功能;见 [QUIC-TRANSPORT] 的第 8.1 节

4.8. TLS 错误

如果 TLS 遇到错误,它会按 [TLS13] 的第 6 节 中的定义生成适当的警报。

TLS 警报会转换为 QUIC 连接错误。AlertDescription 值会加上 0x0100,以产生位于 CRYPTO_ERROR 保留范围内的 QUIC 错误码; 见 [QUIC-TRANSPORT] 的第 20.1 节。所得值会在类型为 0x1c 的 QUIC CONNECTION_CLOSE 帧中发送。

QUIC 只能传达 “fatal” 警报级别。在 TLS 1.3 中, “warning” 级别的唯一现有用途是表示连接关闭;见 [TLS13] 的第 6.1 节。由于 QUIC 提供了替代的连接终止机制, 且 TLS 连接仅在遇到错误时才关闭,因此 QUIC 端点 MUST 将来自 TLS 的任何警报都视为 “fatal” 级别。

QUIC 允许使用通用代码来代替具体错误码;见 [QUIC-TRANSPORT] 的第 11 节。 对于 TLS 警报,这包括用通用警报替换任何警报,例如 handshake_failure(在 QUIC 中为 0x0128)。端点 MAY 使用通用错误码,以避免可能暴露机密信息。

4.9. 丢弃未使用的密钥

在 QUIC 完成向新加密级别的迁移后,可以丢弃先前加密级别的 数据包保护密钥。这在握手期间会发生数次,也会在密钥更新时发生; 见 第 6 节

新密钥可用时,数据包保护密钥不会立即被丢弃。如果来自较低加密级别的 数据包包含 CRYPTO 帧,重传该数据的帧 MUST 以相同加密级别发送。 同样,端点会为数据包在与被确认数据包相同的加密级别生成确认。 因此,在更新的加密级别的密钥可用后,较低加密级别的密钥仍可能 在短时间内需要使用。

端点不能丢弃给定加密级别的密钥,除非它已收到来自对等方在该 加密级别的所有密码学握手消息,且其对等方也已如此。用于确定这一点的 不同方法分别针对 Initial 密钥(第 4.9.1 节)和 Handshake 密钥(第 4.9.2 节)给出。 这些方法并不阻止在该加密级别接收或发送数据包,因为对等方可能尚未收到 所有必要的确认。

尽管端点可能保留较旧密钥,新数据 MUST 以当前可用的最高加密级别发送。只有 ACK 帧和 CRYPTO 帧中数据的重传会在先前加密级别发送。这些数据包 MAY 也包含 PADDING 帧。

4.9.1. 丢弃 Initial 密钥

受 Initial secrets(第 5.2 节)保护的数据包未被认证, 这意味着攻击者可以伪造数据包,意图干扰连接。为限制这些攻击, Initial 数据包保护密钥比其他密钥更激进地丢弃。

成功使用 Handshake 数据包表明不再需要交换 Initial 数据包, 因为这些密钥只能在收到来自 Initial 数据包的所有 CRYPTO 帧之后产生。 因此,客户端在首次发送 Handshake 数据包时 MUST 丢弃 Initial 密钥,而服务器在首次成功处理 Handshake 数据包时 MUST 丢弃 Initial 密钥。端点 MUST NOT 在此之后发送 Initial 数据包。

这会导致放弃 Initial 加密级别的丢包恢复状态,并忽略任何 未完成的 Initial 数据包。

4.9.2. 丢弃 Handshake 密钥

当 TLS 握手被确认时(第 4.1.2 节), 端点 MUST 丢弃其 Handshake 密钥。

4.9.3. 丢弃 0-RTT 密钥

0-RTT 和 1-RTT 数据包共享同一数据包号空间, 并且客户端在发送 1-RTT 数据包之后不会再发送 0-RTT 数据包 (第 5.6 节)。

因此,客户端在安装 1-RTT 密钥后 SHOULD 立即丢弃 0-RTT 密钥,因为此后它们不再有用。

此外,服务器在收到 1-RTT 数据包后 MAY 立即丢弃 0-RTT 密钥。然而,由于数据包重排序,0-RTT 数据包可能在 1-RTT 数据包之后到达。 服务器 MAY 临时保留 0-RTT 密钥, 以允许解密重排序的数据包,而无需将其内容用 1-RTT 密钥重传。 收到 1-RTT 数据包后,服务器 MUST 在短时间内丢弃 0-RTT 密钥;RECOMMENDED 的时间段是探测超时(PTO,见 [QUIC-RECOVERY])的三倍。如果服务器确定已收到所有 0-RTT 数据包,则 MAY 更早丢弃 0-RTT 密钥; 这可以通过跟踪缺失的数据包号来完成。

5. 数据包保护

与 TCP 上的 TLS 一样,QUIC 使用从 TLS 握手派生的密钥保护数据包,并使用 TLS 协商的 AEAD 算法 [AEAD]

QUIC 数据包根据其类型具有不同的保护:

本节描述如何将数据包保护应用于 Handshake 数据包、 0-RTT 数据包和 1-RTT 数据包。同一数据包保护过程也应用于 Initial 数据包。然而,由于确定 Initial 数据包所用的密钥非常简单, 因此这些数据包不被认为具有机密性或完整性保护。Retry 数据包使用固定密钥, 因此同样缺乏机密性和完整性保护。

5.1. 数据包保护密钥

QUIC 派生数据包保护密钥的方式与 TLS 派生记录 保护密钥的方式相同。

每个加密级别都有独立的机密值,用于保护各个方向发送的 数据包。这些流量机密由 TLS 派生(见 [TLS13] 的第 7.1 节),并由 QUIC 用于除 Initial 加密级别之外的所有加密级别。Initial 加密级别的机密基于客户端的 初始 Destination Connection ID 计算,如 第 5.2 节 所述。

用于数据包保护的密钥使用 TLS 提供的 KDF 从 TLS 机密计算得出。 在 TLS 1.3 中,使用 [TLS13] 的第 7.1 节 中描述的 HKDF-Expand-Label 函数,并使用来自所协商 密码套件的哈希函数。QUIC 中所有对 HKDF-Expand-Label 的使用都使用 零长度 Context。

注意,标签以字符串描述,使用 ASCII [ASCII] 编码为字节,不带引号,也不带任何尾随 NUL 字节。

其他 TLS 版本 MUST 提供类似的 函数,才能与 QUIC 一起使用。

当前加密级别机密和标签 “quic key” 会作为 KDF 的输入, 以生成 AEAD 密钥;标签 “quic iv” 用于派生 初始化向量(IV);见 第 5.3 节。标头 保护密钥使用 “quic hp” 标签;见 第 5.4 节。 使用这些标签在 QUIC 和 TLS 之间提供密钥 分离;见 第 9.6 节

“quic key” 和 “quic hp” 都用于生成密钥,因此与这些标签一起 提供给 HKDF-Expand-Label 的 Length 由 AEAD 或标头保护算法中的 密钥大小决定。与 “quic iv” 一起提供的 Length 是 AEAD nonce 的 最小长度;如果 8 字节更大,则为 8 字节;见 [AEAD]

用于 Initial secrets 的 KDF 始终是来自 TLS 1.3 的 HKDF-Expand-Label 函数;见 第 5.2 节

5.2. Initial 机密

Initial 数据包应用数据包保护过程,但使用从客户端第一个 Initial 数据包中的 Destination Connection ID 字段派生的机密。

该机密通过使用 HKDF-Extract(见 [HKDF] 的第 2.2 节) 来确定,其中 salt 为 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a, 输入密钥材料(IKM)为 Destination Connection ID 字段。这会产生一个 中间伪随机密钥(PRK),用于派生两个独立的机密,分别用于发送和接收。

客户端用于构造 Initial 数据包的机密以 PRK 和标签 “client in” 作为 TLS [TLS13] 中 HKDF-Expand-Label 函数的输入, 以生成一个 32 字节的机密。服务器构造的数据包使用相同过程, 但标签为 “server in”。派生 Initial 机密和密钥时,HKDF 使用的哈希函数是 SHA-256 [SHA]

该过程的伪代码如下:

initial_salt = 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a
initial_secret = HKDF-Extract(initial_salt,
                              client_dst_connection_id)

client_initial_secret = HKDF-Expand-Label(initial_secret,
                                          "client in", "",
                                          Hash.length)
server_initial_secret = HKDF-Expand-Label(initial_secret,
                                          "server in", "",
                                          Hash.length)

与 HKDF-Expand-Label 一起使用的连接 ID 是客户端发送的 Initial 数据包中的 Destination Connection ID。除非客户端在收到 Retry 数据包后创建 Initial 数据包,此时 Destination Connection ID 由服务器选择; 否则这将是一个随机选择的值。

QUIC 的未来版本 SHOULD 生成新的 salt 值,从而确保每个 QUIC 版本的密钥都不同。这可以防止只识别 某一个 QUIC 版本的中间盒查看或修改未来版本的数据包内容。

即使所提供的 TLS 版本不包含 TLS 1.3,也 MUST 对 Initial 数据包使用 TLS 1.3 中定义的 HKDF-Expand-Label 函数。

当服务器发送 Retry 数据包时,用于构造后续 Initial 数据包的 机密会改变,以使用服务器选择的连接 ID 值。当客户端响应来自服务器的 Initial 数据包而更改其使用的 Destination Connection ID 时,机密不会改变。

附录 A 包含示例 Initial 数据包。

5.3. AEAD 使用

用于 QUIC 数据包保护的带关联数据的认证加密(AEAD)函数 (见 [AEAD])是为与 TLS 连接一起使用而协商出的 AEAD。例如,如果 TLS 使用 TLS_AES_128_GCM_SHA256 密码套件,则使用 AEAD_AES_128_GCM 函数。

QUIC 可以使用 [TLS13] 中定义的任何密码套件,但 TLS_AES_128_CCM_8_SHA256 除外。除非为某个密码套件定义了 标头保护方案,否则 MUST NOT 协商该密码套件。 除 TLS_AES_128_CCM_8_SHA256 外,本文档为 [TLS13] 中定义的所有密码套件定义了 标头保护方案。这些密码套件具有 16 字节认证标签,其输出比输入大 16 字节。

端点 MUST NOT 拒绝提供了其 不支持密码套件的 ClientHello,否则将无法部署新的密码套件。这也适用于 TLS_AES_128_CCM_8_SHA256。

构造数据包时,AEAD 函数先于标头保护应用;见 第 5.4 节。未受保护的 数据包标头是关联数据(A)的一部分。处理数据包时,端点首先 移除标头保护。

数据包的密钥和 IV 按 第 5.1 节 所述计算。 nonce N 通过将数据包保护 IV 与数据包号组合而形成。重构后的 QUIC 数据包号的 62 位以网络字节序表示,并在左侧用零填充到 IV 的 大小。填充后的数据包号与 IV 的异或形成 AEAD nonce。

AEAD 的关联数据 A 是 QUIC 标头的内容,从短标头或长标头的 第一个字节开始,直到并包括未受保护的数据包号。

AEAD 的输入明文 P 是 QUIC 数据包的载荷,如 [QUIC-TRANSPORT] 中所述。

AEAD 的输出密文 C 会替代 P 进行传输。

某些 AEAD 函数对在同一密钥和 IV 下可加密的数据包数量有限制; 见 第 6.6 节。这可能低于数据包号限制。 端点 MUST 在超过正在使用的 AEAD 所设的 任何限制之前发起密钥更新(第 6 节)。

5.4. 标头保护

QUIC 数据包标头的部分字段,特别是 Packet Number 字段, 使用与数据包保护密钥和 IV 分开派生的密钥进行保护。使用 “quic hp” 标签派生的密钥用于为那些不暴露给路径上元素的字段 提供机密性保护。

此保护应用于第一个字节的最低有效位,以及 Packet Number 字段。 对于长标头数据包,第一个字节的四个最低有效位受到保护;对于短标头 数据包,第一个字节的五个最低有效位受到保护。对于两种标头形式, 这都覆盖保留位和 Packet Number Length 字段;对于短标头数据包, Key Phase 位也受到保护。

同一标头保护密钥在连接持续期间使用,其值在密钥更新后不会改变 (见 第 6 节)。这允许使用标头保护来保护 Key Phase。

此过程不适用于 Retry 或 Version Negotiation 数据包,因为它们 不包含受保护载荷,也不包含此过程保护的任何字段。

5.4.1. 标头 保护应用

标头保护在数据包保护应用之后应用(见 第 5.3 节)。 对数据包的密文进行采样,并将其用作加密算法的输入。 所用算法取决于协商的 AEAD。

该算法的输出是一个 5 字节掩码,通过异或应用到受保护的 标头字段。数据包第一个字节的最低有效位由第一个掩码字节的 最低有效位掩蔽,数据包号则由其余字节掩蔽。较短的数据包号编码 可能导致未使用的掩码字节,这些字节不会被使用。

图 6 展示了应用 标头保护的示例算法。移除标头保护仅在确定数据包号长度 (pn_length)的顺序上有所不同(此处使用 “^” 表示异或)。

mask = header_protection(hp_key, sample)

pn_length = (packet[0] & 0x03) + 1
if (packet[0] & 0x80) == 0x80:
   # Long header: 4 bits masked
   packet[0] ^= mask[0] & 0x0f
else:
   # Short header: 5 bits masked
   packet[0] ^= mask[0] & 0x1f

# pn_offset is the start of the Packet Number field.
packet[pn_offset:pn_offset+pn_length] ^= mask[1:1+pn_length]
图 6标头保护 伪代码

具体的标头保护函数根据所选密码套件定义; 见 第 5.4.3 节第 5.4.4 节

图 7 展示了一个 长标头数据包(Initial)和一个短标头数据包(1-RTT)的示例。 图 7 展示了每个标头中由标头保护覆盖的 字段,以及被采样的受保护数据包载荷部分。

Initial Packet {
  Header Form (1) = 1,
  Fixed Bit (1) = 1,
  Long Packet Type (2) = 0,
  Reserved Bits (2),         # Protected
  Packet Number Length (2),  # Protected
  Version (32),
  DCID Len (8),
  Destination Connection ID (0..160),
  SCID Len (8),
  Source Connection ID (0..160),
  Token Length (i),
  Token (..),
  Length (i),
  Packet Number (8..32),     # Protected
  Protected Payload (0..24), # Skipped Part
  Protected Payload (128),   # Sampled Part
  Protected Payload (..)     # Remainder
}

1-RTT Packet {
  Header Form (1) = 0,
  Fixed Bit (1) = 1,
  Spin Bit (1),
  Reserved Bits (2),         # Protected
  Key Phase (1),             # Protected
  Packet Number Length (2),  # Protected
  Destination Connection ID (0..160),
  Packet Number (8..32),     # Protected
  Protected Payload (0..24), # Skipped Part
  Protected Payload (128),   # Sampled Part
  Protected Payload (..),    # Remainder
}
图 7标头保护 和密文样本

在 TLS 密码套件可与 QUIC 一起使用之前, MUST 为该密码套件所用的 AEAD 指定 标头保护算法。本文档为 AEAD_AES_128_GCM、AEAD_AES_128_CCM、 AEAD_AES_256_GCM(所有这些 AES AEAD 均定义于 [AEAD]) 以及 AEAD_CHACHA20_POLY1305 (定义于 [CHACHA])定义了算法。 在 TLS 选择密码套件之前,使用 AES 标头保护(第 5.4.3 节), 与 AEAD_AES_128_GCM 数据包保护相匹配。

5.4.2. 标头保护 样本

标头保护算法同时使用标头保护密钥和来自数据包 Payload 字段的密文样本。

采样的字节数始终相同,但需要为接收端点移除保护留出余地, 因为接收端点并不知道 Packet Number 字段的长度。密文样本从 Packet Number 字段起始位置之后 4 字节的偏移处开始取得。 也就是说,在为标头保护采样数据包密文时,假定 Packet Number 字段 为 4 字节长(其最大可能编码长度)。

端点 MUST 丢弃长度不足以包含完整 样本的数据包。

为确保有足够数据可供采样,数据包会被填充,使编码后的 数据包号与受保护载荷的组合长度至少比标头保护所需样本长 4 字节。[TLS13] 中定义的密码套件—— 除 TLS_AES_128_CCM_8_SHA256 外,本文档未为其定义标头保护方案—— 具有 16 字节扩展和 16 字节标头保护样本。如果数据包号编码为单字节, 这导致未受保护载荷中至少需要 3 字节帧;如果数据包号编码为 2 字节,则至少需要 2 字节帧。

采样的密文可由以下伪代码确定:

# pn_offset is the start of the Packet Number field.
sample_offset = pn_offset + 4

sample = packet[sample_offset..sample_offset+sample_length]

短标头数据包的数据包号偏移可计算为:

pn_offset = 1 + len(connection_id)

长标头数据包的数据包号偏移可计算为:

pn_offset = 7 + len(destination_connection_id) +
                len(source_connection_id) +
                len(payload_length)
if packet_type == Initial:
    pn_offset += len(token_length) +
                 len(token)

例如,对于一个短标头数据包,如果连接 ID 为 8 字节, 并且使用 AEAD_AES_128_GCM 保护,则样本取第 13 到第 28 字节 (含端点,使用从零开始的索引)。

同一 UDP 数据报中可能包含多个 QUIC 数据包。 每个数据包都单独处理。

5.4.3. 基于 AES 的 标头保护

本节定义 AEAD_AES_128_GCM、 AEAD_AES_128_CCM 和 AEAD_AES_256_GCM 的数据包保护算法。 AEAD_AES_128_GCM 和 AEAD_AES_128_CCM 使用电子密码本(ECB)模式的 128 位 AES。AEAD_AES_256_GCM 使用 ECB 模式的 256 位 AES。AES 定义于 [AES]

该算法从数据包密文中采样 16 字节。该值用作 AES-ECB 的输入。在伪代码中,标头保护函数定义如下:

header_protection(hp_key, sample):
  mask = AES-ECB(hp_key, sample)

5.4.4. 基于 ChaCha20 的 标头保护

当使用 AEAD_CHACHA20_POLY1305 时,标头保护使用 [CHACHA] 的第 2.4 节 中定义的原始 ChaCha20 函数。该函数使用 256 位密钥和从数据包保护输出中采样的 16 字节。

采样密文的前 4 字节是块计数器。ChaCha20 实现可以接受 32 位整数来代替字节序列,在这种情况下, 该字节序列被解释为小端值。

其余 12 字节用作 nonce。ChaCha20 实现可以接受三个 32 位整数的数组来代替字节序列,在这种情况下, nonce 字节被解释为一系列 32 位小端整数。

加密掩码通过调用 ChaCha20 来保护 5 个零字节而产生。 在伪代码中,标头保护函数定义如下:

header_protection(hp_key, sample):
  counter = sample[0..3]
  nonce = sample[4..15]
  mask = ChaCha20(hp_key, counter, nonce, {0,0,0,0,0})

5.5. 接收受保护的 数据包

一旦端点成功接收具有给定数据包号的数据包,它 MUST 丢弃同一数据包号空间中具有更高数据包号、 且无法使用相同密钥或——如果存在密钥更新——后续数据包保护密钥 成功解除保护的所有数据包;见 第 6 节。同样,似乎触发密钥更新但 无法成功解除保护的数据包 MUST 被丢弃。

解除数据包保护失败并不一定表示对等方存在协议错误或存在攻击。 QUIC 中使用的截断数据包号编码可能会在数据包显著延迟时导致 数据包号被错误解码。

5.6. 0-RTT 密钥的使用

如果 0-RTT 密钥可用(见 第 4.6.1 节),由于缺少重放保护, 必须限制其使用,以避免对协议的重放攻击。

[QUIC-TRANSPORT] 中定义的帧中,STREAM、RESET_STREAM、 STOP_SENDING 和 CONNECTION_CLOSE 帧在 0-RTT 中使用时可能不安全, 因为它们承载应用数据。服务器在 0-RTT 中收到的应用数据可能导致 服务器上的应用多次处理该数据,而不是只处理一次。服务器因处理重放的 应用数据而采取的额外操作可能产生不良后果。因此,除非正在使用的应用 明确请求,否则客户端 MUST NOT 将 0-RTT 用于应用数据。

使用 QUIC 的应用协议 MUST 包含一个 配置文件,定义 0-RTT 的可接受使用方式;否则,0-RTT 只能用于承载 不承载应用数据的 QUIC 帧。例如,HTTP 的配置文件在 [HTTP-REPLAY] 中描述,并用于 HTTP/3;见 [QUIC-HTTP] 的第 10.9 节

虽然重放数据包可能导致额外的连接尝试,但处理不承载应用数据的 重放帧的影响仅限于改变受影响连接的状态。使用重放数据包无法成功 完成 TLS 握手。

客户端 MAY 希望在 TLS 握手完成之前 对其发送的数据施加额外限制。

除此之外,客户端将 0-RTT 密钥视为等同于 1-RTT 密钥, 但它不能使用 0-RTT 密钥发送某些帧;见 [QUIC-TRANSPORT] 的第 12.5 节

收到服务器已接受其 0-RTT 数据指示的客户端,可以在收到服务器的 所有握手消息之前发送 0-RTT 数据。如果客户端收到 0-RTT 数据已被 拒绝的指示,它 SHOULD 停止发送 0-RTT 数据。

服务器 MUST NOT 使用 0-RTT 密钥保护 数据包;它使用 1-RTT 密钥来保护对 0-RTT 数据包的确认。客户端 MUST NOT 尝试解密其收到的 0-RTT 数据包, 而是 MUST 丢弃它们。

一旦客户端安装了 1-RTT 密钥,它 MUST NOT 再发送任何 0-RTT 数据包。

5.7. 接收乱序的受保护 数据包

由于重排序和丢失,端点可能在收到最终 TLS 握手消息之前 收到受保护的数据包。客户端将无法解密来自服务器的 1-RTT 数据包, 而服务器能够解密来自客户端的 1-RTT 数据包。任一角色中的端点 MUST NOT 在完成握手之前解密来自其对等方的 1-RTT 数据包。

即使服务器在收到来自客户端的第一批握手消息后就可以使用 1-RTT 密钥,它仍缺少关于客户端状态的保证:

  • 客户端尚未认证,除非服务器选择使用 预共享密钥,并验证了客户端的预共享密钥 binder;见 [TLS13] 的第 4.2.11 节
  • 客户端尚未证明其活性,除非服务器已通过 Retry 数据包或其他方式验证了客户端地址;见 [QUIC-TRANSPORT] 的第 8.1 节
  • 服务器响应的任何已接收 0-RTT 数据 可能源自重放攻击。

因此,服务器在握手完成之前使用 1-RTT 密钥仅限于发送数据。 服务器 MUST NOT 在 TLS 握手完成之前处理传入的 1-RTT 受保护数据包。由于发送确认表示已处理一个数据包中的所有帧, 因此服务器在 TLS 握手完成之前不能为 1-RTT 数据包发送确认。 受 1-RTT 密钥保护的已接收数据包 MAY 被存储, 并在握手完成后稍后解密和使用。

服务器等待客户端 Finished 消息的要求产生了对该消息交付的依赖。 客户端可以通过将其 1-RTT 数据包与包含承载 Finished 消息的 CRYPTO 帧副本的 Handshake 数据包合并发送,来避免这所暗含的队头阻塞可能性, 直到其中一个 Handshake 数据包得到确认。这使服务器能够立即处理这些数据包。

服务器可能在收到 TLS ClientHello 之前收到受 0-RTT 密钥保护的 数据包。服务器 MAY 保留这些数据包,以便在预期收到 ClientHello 后稍后解密。

客户端通常在握手完成的同时收到 1-RTT 密钥。即使客户端拥有 1-RTT 机密,它也 MUST NOT 在 TLS 握手完成之前处理 传入的 1-RTT 受保护数据包。

5.8. Retry 数据包完整性

Retry 数据包(见 [QUIC-TRANSPORT] 的第 17.2.5 节)承载 Retry Integrity Tag,该标签提供两个属性:它允许丢弃在网络中被意外损坏的 数据包,并且只有观察到 Initial 数据包的实体才能发送有效的 Retry 数据包。

Retry Integrity Tag 是一个 128 位字段,作为使用以下输入的 AEAD_AES_128_GCM [AEAD] 的输出计算:

  • 机密密钥 K 为 128 位,等于 0xbe0c690b9f66575a1d766b54e368c84e。
  • nonce N 为 96 位,等于 0x461599d35d632bf2239825bb。
  • 明文 P 为空。
  • 关联数据 A 是 Retry Pseudo-Packet 的内容,如 图 8 所示:

机密密钥和 nonce 是通过调用 HKDF-Expand-Label 派生的值, 使用 0xd9c9943e6101fd200021506bcc02814c73030f25c79d71ce876eca876e6fca8e 作为机密,并使用 “quic key” 和 “quic iv” 标签(第 5.1 节)。

Retry Pseudo-Packet {
  ODCID Length (8),
  Original Destination Connection ID (0..160),
  Header Form (1) = 1,
  Fixed Bit (1) = 1,
  Long Packet Type (2) = 3,
  Unused (4),
  Version (32),
  DCID Len (8),
  Destination Connection ID (0..160),
  SCID Len (8),
  Source Connection ID (0..160),
  Retry Token (..),
}
图 8Retry Pseudo-Packet

Retry Pseudo-Packet 不在线上传输。它通过取得已传输的 Retry 数据包、移除 Retry Integrity Tag,并在前面添加以下两个字段来计算:

ODCID Length:

ODCID Length 字段包含其后 Original Destination Connection ID 字段的字节长度,编码为 8 位无符号 整数。

Original Destination Connection ID:

Original Destination Connection ID 包含此 Retry 所响应的 Initial 数据包中的 Destination Connection ID 的值。该字段的长度由 ODCID Length 给出。 此字段的存在确保有效的 Retry 数据包只能由观察到 Initial 数据包的 实体发送。

6. 密钥更新

一旦握手被确认(见 第 4.1.2 节),端点 MAY 发起密钥更新。

Key Phase 位指示用于保护数据包的数据包保护密钥。对于第一组 1-RTT 数据包,Key Phase 位初始设置为 0,并通过翻转来表示每次后续密钥更新。

Key Phase 位允许接收方检测密钥材料的变化,而无需收到触发该变化的 第一个数据包。注意到 Key Phase 位变化的端点会更新密钥,并解密包含 该变化值的数据包。

发起密钥更新会导致两个端点都更新密钥。这与 TLS 不同, 在 TLS 中端点可以独立更新密钥。

此机制取代了 TLS 的密钥更新机制,后者依赖使用 1-RTT 加密密钥发送的 KeyUpdate 消息。端点 MUST NOT 发送 TLS KeyUpdate 消息。端点 MUST 将收到 TLS KeyUpdate 消息视为类型 0x010a 的连接错误,相当于 unexpected_message 的 fatal TLS 警报;见 第 4.8 节

图 9 展示了密钥更新过程, 其中最初使用的一组密钥(以 @M 标识)被更新后的密钥(以 @N 标识)替换。 Key Phase 位的值用方括号 [] 表示。

   Initiating Peer                    Responding Peer

@M [0] QUIC Packets

... Update to @N
@N [1] QUIC Packets
                      -------->
                                         Update to @N ...
                                      QUIC Packets [1] @N
                      <--------
                                      QUIC Packets [1] @N
                                    containing ACK
                      <--------
... Key Update Permitted

@N [1] QUIC Packets
         containing ACK for @N packets
                      -------->
                                 Key Update Permitted ...
图 9密钥更新

6.1. 发起密钥 更新

端点为数据包保护维护独立的读取和写入机密。端点通过更新其 数据包保护写入机密,并使用它来保护新数据包,从而发起密钥更新。 端点从现有写入机密创建新的写入机密,如 [TLS13] 的第 7.2 节 中所执行的那样。这使用 TLS 提供的 KDF 函数,并带有标签 “quic ku”。相应的密钥和 IV 按 第 5.1 节 中的定义从该机密创建。 标头保护密钥不会更新。

例如,要使用 TLS 1.3 更新写入密钥,可按如下方式使用 HKDF-Expand-Label:

secret_<n+1> = HKDF-Expand-Label(secret_<n>, "quic ku",
                                 "", Hash.length)

端点翻转 Key Phase 位的值,并使用更新后的密钥和 IV 保护所有后续数据包。

端点在确认握手之前 MUST NOT 发起密钥更新(第 4.1.2 节)。 端点 MUST NOT 发起后续密钥更新,除非它已收到对使用 当前密钥阶段的密钥保护而发送的数据包的确认。这确保在可以发起另一次 密钥更新之前,两个对等方都可以使用密钥。这可以通过跟踪每个密钥阶段 发送的最低数据包号,以及 1-RTT 空间中已确认的最高数据包号来实现: 一旦后者大于或等于前者,即可发起另一次密钥更新。

发起密钥更新的端点也会更新其用于接收数据包的密钥。 这些密钥将用于处理对等方在更新后发送的数据包。

端点 MUST 保留旧密钥,直到它已成功解除保护 一个使用新密钥发送的数据包。端点 SHOULD 在解除保护 使用新密钥发送的数据包后继续保留旧密钥一段时间。过早丢弃旧密钥可能导致 延迟的数据包被丢弃。丢弃数据包会被对等方解释为丢包,并可能对性能产生 不利影响。

6.2. 响应密钥 更新

在收到当前密钥阶段中数据包的确认后,对等方允许发起密钥更新。 当处理一个 Key Phase 与用于保护其最后发送数据包的值不同的数据包时, 端点检测到密钥更新。为处理此数据包,端点使用下一组数据包保护密钥和 IV。 关于生成这些密钥的考虑,见 第 6.3 节

如果使用下一组密钥和 IV 成功处理了数据包,则对等方已经发起 密钥更新。端点 MUST第 6.1 节 中所述,更新其发送密钥到相应的密钥阶段。 在发送对使用更新后密钥收到的数据包的确认之前,发送密钥 MUST 更新。通过在使用更新后密钥保护的数据包中 确认触发密钥更新的数据包,端点表明密钥更新已完成。

端点可以根据其正常的数据包发送行为推迟发送数据包或确认; 没有必要立即生成一个数据包来响应密钥更新。端点发送的下一个数据包将 使用更新后的密钥。下一个包含确认的数据包会使密钥更新完成。如果端点在 尚未发送任何使用更新后密钥、且包含对发起密钥更新数据包的确认的数据包之前 检测到第二次更新,则表明其对等方已在未等待确认的情况下更新密钥两次。 端点 MAY 将这种连续密钥更新视为 KEY_UPDATE_ERROR 类型的连接错误。

端点收到使用旧密钥保护的数据包中承载的确认,且其中任何被确认的数据包 是使用较新密钥保护的,则端点 MAY 将其视为 KEY_UPDATE_ERROR 类型的连接错误。这表明对等方已收到并确认了发起 密钥更新的数据包,但未响应更新密钥。

6.3. 接收密钥生成的 时机

响应表面上密钥更新的端点 MUST NOT 生成可能表示 Key Phase 位无效的 计时侧信道信号(见 第 9.5 节)。当密钥更新尚未允许时, 端点可以使用随机化的数据包保护密钥代替已丢弃的密钥。使用随机化密钥可确保 尝试移除数据包保护不会导致计时差异,并会导致带有无效 Key Phase 位的 数据包被拒绝。

创建用于接收数据包的新数据包保护密钥的过程,可能会暴露已经发生 密钥更新。端点 MAY 在数据包处理过程中生成新密钥, 但这会创建计时信号,攻击者可用它来获知密钥更新发生的时间,从而泄露 Key Phase 位的值。

通常期望端点已准备好当前和下一组接收数据包保护密钥。 在密钥更新完成后的一小段时间内,最长到 PTO,端点 MAY 推迟生成下一组接收数据包保护密钥。这允许端点 只保留两组接收密钥;见 第 6.5 节

一旦生成,下一组数据包保护密钥 SHOULD 被保留,即使收到的数据包 随后被丢弃。包含表面上密钥更新的数据包很容易伪造,虽然密钥更新过程 不需要大量工作,但触发此过程可能被攻击者用于 DoS。

因此,端点 MUST 能够保留两组用于接收数据包的 数据包保护密钥:当前的和下一组。除了这些密钥之外再保留先前密钥可能会 改善性能,但这不是必需的。

6.4. 使用已更新密钥 发送

端点永远不会发送受旧密钥保护的数据包。只使用当前密钥。 用于保护数据包的密钥可以在切换到更新密钥后立即丢弃。

具有较高数据包号的数据包 MUST 使用与较低数据包号数据包相同或更新的数据包保护密钥来保护。 如果在较低数据包号的数据包已使用较新密钥的情况下,端点仍成功使用旧密钥 移除保护,则它 MUST 将此视为 KEY_UPDATE_ERROR 类型的连接错误。

6.5. 使用不同密钥 接收

在密钥更新期间接收数据包时,如果数据包因网络延迟而受较旧密钥保护, 它们可能会到达。保留旧数据包保护密钥可使这些数据包被成功处理。

由于来自下一密钥阶段的密钥保护的数据包使用的 Key Phase 值,与来自上一密钥阶段的密钥保护的数据包相同,因此如果要处理 受旧密钥保护的数据包,就必须区分两者。这可以使用数据包号完成。 低于当前密钥阶段中任何数据包号的恢复数据包号使用先前的数据包保护密钥; 高于当前密钥阶段中任何数据包号的恢复数据包号则需要使用下一组数据包 保护密钥。

需要谨慎确保在先前、当前和下一组数据包保护密钥之间选择的任何过程 不会暴露计时侧信道,从而泄露用于移除数据包保护的是哪组密钥。 更多信息见 第 9.5 节

或者,端点可以只保留两组数据包保护密钥,在经过足够时间以允许网络中 发生重排序之后,用下一组替换先前的一组。在这种情况下,仅使用 Key Phase 位即可选择密钥。

在将下一组接收密钥提升为当前密钥之后,端点 MAY 允许大约一个 探测超时(PTO;见 [QUIC-RECOVERY])的时间段, 然后再创建后续的数据包保护密钥。这些更新后的 密钥 MAY 在那时替换先前密钥。需要注意的是, PTO 是一个主观度量——也就是说,对等方可能对 RTT 有不同看法—— 此时间预计足够长,使任何重排序的数据包即使得到确认,也会被对等方宣布为丢失; 同时又足够短,以允许对等方发起进一步密钥更新。

端点需要考虑这样一种可能性:在对等方保留旧密钥期间,对等方可能 无法解密发起密钥更新的数据包。端点在收到确认先前密钥更新已被接收的确认之后, SHOULD 等待三倍 PTO 再发起 密钥更新。未留出足够时间可能导致数据包被丢弃。

端点在收到使用新密钥保护的数据包后,保留旧读取密钥的时间 SHOULD 不超过三倍 PTO。 经过此时间段后,旧读取密钥及其相应机密 SHOULD 被丢弃。

6.6. AEAD 使用限制

本文档为 AEAD 算法设定使用限制,以确保在使用 QUIC 时, 过度使用不会使对手在攻击通信机密性和完整性方面获得不成比例的优势。

TLS 1.3 中定义的使用限制存在于针对机密性攻击的保护, 并适用于 AEAD 保护的成功应用。认证加密中的完整性保护还依赖于 限制伪造数据包尝试的次数。TLS 通过在任何记录未通过认证检查后关闭连接 来实现这一点。相比之下,QUIC 会忽略任何无法认证的数据包, 从而允许多次伪造尝试。

QUIC 分别考虑 AEAD 机密性和完整性限制。机密性限制适用于 使用给定密钥加密的数据包数量。完整性限制适用于给定连接内解密的数据包数量。 下面给出对每种 AEAD 算法执行这些限制的详细信息。

端点 MUST 统计每组密钥加密的数据包数量。 如果使用同一密钥加密的数据包总数超过所选 AEAD 的机密性限制, 端点 MUST 停止使用这些 密钥。端点 MUST 在发送超过所选 AEAD 机密性限制所允许的 受保护数据包数量之前发起密钥更新。如果无法进行密钥更新或达到完整性限制, 端点 MUST 停止使用 该连接,并且在收到数据包时只发送无状态重置。RECOMMENDED 端点在达到无法进行密钥更新的状态之前,立即以类型为 AEAD_LIMIT_REACHED 的连接错误关闭连接。

对于 AEAD_AES_128_GCM 和 AEAD_AES_256_GCM,机密性限制是 223 个加密数据包;见 附录 B.1。对于 AEAD_CHACHA20_POLY1305,机密性限制大于可能的数据包数量 (262),因此可以忽略。对于 AEAD_AES_128_CCM,机密性限制是 221.5 个加密 数据包;见 附录 B.2。应用限制会降低攻击者 将正在使用的 AEAD 与随机置换区分开的概率;见 [AEBounds][ROBUST][GCM-MU]

除了统计已发送的数据包之外,端点 MUST 统计连接生命周期内接收且认证失败的数据包数量。 如果连接中跨所有密钥的认证失败接收数据包总数超过所选 AEAD 的完整性限制, 端点 MUST 立即以类型为 AEAD_LIMIT_REACHED 的连接错误关闭连接,并且不再处理任何数据包。

对于 AEAD_AES_128_GCM 和 AEAD_AES_256_GCM,完整性限制是 252 个无效数据包;见 附录 B.1。对于 AEAD_CHACHA20_POLY1305,完整性 限制是 236 个无效数据包;见 [AEBounds]。对于 AEAD_AES_128_CCM, 完整性限制是 221.5 个无效数据包;见 附录 B.2。应用此限制会降低攻击者 成功伪造数据包的概率;见 [AEBounds][ROBUST][GCM-MU]

限制数据包大小的端点 MAY 使用 更高的机密性和完整性限制;详见 附录 B

未来的分析和规范 MAY 放宽 某个 AEAD 的机密性或完整性限制。

任何被指定用于 QUIC 的 TLS 密码套件 MUST 定义相关 AEAD 函数的使用限制,以保留 机密性和完整性余量。也就是说,必须为可认证的数据包数量以及认证失败的 数据包数量指定限制。提供这些值所基于的任何分析的引用——以及该分析中使用的 任何假设——可使这些限制适应不同的使用条件。

6.7. 密钥更新错误码

KEY_UPDATE_ERROR 错误码(0x0e)用于表示与密钥更新相关的错误。

7. Initial 消息的安全性

Initial 数据包不使用机密密钥进行保护,因此可能受到攻击者的篡改。 QUIC 提供针对无法读取数据包的攻击者的保护,但不试图针对攻击者能够观察并注入 数据包的攻击提供额外保护。某些形式的篡改——例如修改 TLS 消息本身——是可检测的, 但另一些形式——例如修改 ACK——则不可检测。

例如,攻击者可以注入包含 ACK 帧的数据包,使其看起来像某个数据包 尚未被接收,或者造成对连接状态的错误印象(例如,通过修改 ACK Delay)。 注意,这类数据包可能导致合法数据包被作为重复包丢弃。实现 SHOULD 谨慎依赖 Initial 数据包中包含的、未以其他方式认证的任何数据。

攻击者也可能篡改 Handshake 数据包中承载的数据,但由于这种篡改需要修改 TLS 握手消息,任何此类篡改都会导致 TLS 握手失败。

8. 对 TLS 握手的 QUIC 特定调整

TLS 握手的某些方面在与 QUIC 一起使用时有所不同。

QUIC 还需要 TLS 提供附加特性。除了协商密码学参数之外,TLS 握手还会承载并认证 QUIC 传输参数的值。

8.1. 协议协商

QUIC 要求密码学握手提供经认证的协议协商。TLS 使用应用层协议协商 [ALPN] 来选择应用协议。除非使用另一种机制 来就应用协议达成一致,否则端点 MUST 为此目的使用 ALPN。

使用 ALPN 时,如果未协商出应用协议,端点 MUST 立即关闭连接(见 第 10.2 节,[QUIC-TRANSPORT]),并使用 no_application_protocol TLS 警报(QUIC 错误码 0x0178;见 第 4.8 节)。 虽然 [ALPN] 只规定服务器使用此警报, QUIC 客户端 MUST 在 ALPN 协商失败时使用错误 0x0178 终止连接。

应用协议 MAY 限制其能够运行其上的 QUIC 版本。服务器 MUST 选择与客户端已选择的 QUIC 版本 兼容的应用协议。服务器 MUST 将无法选择兼容 应用协议视为 0x0178(no_application_protocol)类型的连接错误。 同样,客户端 MUST 将服务器选择了不兼容的 应用协议视为 0x0178 类型的连接错误。

8.2. QUIC 传输 参数扩展

QUIC 传输参数承载在 TLS 扩展中。QUIC 的不同版本 可能会定义不同的传输配置协商方法。

在 TLS 握手中包含传输参数可为这些值提供完整性保护。

   enum {
      quic_transport_parameters(0x39), (65535)
   } ExtensionType;

quic_transport_parameters 扩展的 extension_data 字段包含一个 由正在使用的 QUIC 版本定义的值。

quic_transport_parameters 扩展在握手期间承载于 ClientHello 和 EncryptedExtensions 消息中。端点 MUST 发送 quic_transport_parameters 扩展;收到不带 quic_transport_parameters 扩展的 ClientHello 或 EncryptedExtensions 消息的端点 MUST 以类型为 0x016d 的错误关闭连接(等价于 fatal TLS missing_extension 警报,见 第 4.8 节)。

传输参数会在握手完成之前变得可用。服务器可能会早于握手完成时 使用这些值。然而,传输参数的值直到握手完成才会得到认证, 因此这些参数的任何使用都不能依赖其真实性。对传输参数的任何篡改都会导致 握手失败。

端点 MUST NOT 在不使用 QUIC 的 TLS 连接中发送此扩展(例如 [TLS13] 中定义的 TLS 与 TCP 的使用)。 支持此扩展的实现如果在传输不是 QUIC 时收到该扩展, MUST 发送 fatal unsupported_extension 警报。

协商 quic_transport_parameters 扩展会导致 EndOfEarlyData 被移除;见 第 8.3 节

8.3. 移除 EndOfEarlyData 消息

TLS EndOfEarlyData 消息不与 QUIC 一起使用。QUIC 不依赖 此消息来标记 0-RTT 数据的结束,也不依赖它来表示切换到 Handshake 密钥。

客户端 MUST NOT 发送 EndOfEarlyData 消息。 服务器 MUST 将在 0-RTT 数据包中收到 CRYPTO 帧视为 PROTOCOL_VIOLATION 类型的连接错误。

因此,EndOfEarlyData 不会出现在 TLS 握手记录中。

8.4. 禁止 TLS 中间盒 兼容模式

[TLS13] 的附录 D.4 描述了对 TLS 1.3 握手的一种修改, 作为规避某些中间盒缺陷的解决办法。TLS 1.3 中间盒兼容 模式涉及将 ClientHello 和 ServerHello 中的 legacy_session_id 字段设置为 32 字节值,然后发送 change_cipher_spec 记录。该字段和记录都不承载 语义内容,并会被忽略。

此模式在 QUIC 中没有用途,因为它只适用于干扰 TCP 上 TLS 的 中间盒。QUIC 也不提供承载 change_cipher_spec 记录的手段。客户端 MUST NOT 请求使用 TLS 1.3 兼容模式。服务器 SHOULD 将收到带有非空 legacy_session_id 字段的 TLS ClientHello 视为 PROTOCOL_VIOLATION 类型的连接错误。

9. 安全考虑

适用于 TLS 的所有安全考虑,也适用于 QUIC 中 TLS 的使用。 阅读完整的 [TLS13] 及其附录,是理解 QUIC 安全属性的最佳方式。

本节总结了与 TLS 集成相关的一些更重要的 QUIC 特定安全方面, 尽管本文档其余部分中还有许多与安全相关的细节。

9.1. 会话可关联性

使用 TLS 会话票据允许服务器以及可能的其他实体将同一客户端发起的 连接相关联;详见 第 4.5 节

9.2. 0-RTT 的重放攻击

第 8 节, [TLS13] 所述,使用 TLS early data 会暴露于 重放攻击。QUIC 中使用 0-RTT 同样容易受到重放攻击。

端点 MUST 实现并使用 [TLS13] 中描述的重放保护, 但也承认这些保护并不完美。因此,需要额外考虑重放风险。

除非通过它可能承载的应用协议信息,QUIC 不易受到重放攻击。 基于 [QUIC-TRANSPORT] 中定义的帧类型来管理 QUIC 协议状态,并不容易受到重放影响。 QUIC 帧的处理是幂等的,如果帧被重放、重排序或丢失,也不会导致无效的连接 状态。除 QUIC 所服务的应用协议产生的影响之外,QUIC 连接不会产生超出连接生命周期的影响。

TLS 会话票据和地址验证令牌用于在连接之间承载 QUIC 配置信息,具体而言,用于使服务器能够高效恢复连接建立和地址验证中使用的状态。 它们 MUST NOT 用于在端点之间传达应用语义; 客户端 MUST 将它们视为不透明值。 这些令牌存在复用可能性,这意味着它们需要更强的重放保护。

在连接上接受 0-RTT 的服务器,会比接受不带 0-RTT 的连接承担更高成本。 这包括更高的处理和计算成本。服务器在接受 0-RTT 时需要考虑重放概率以及 所有关联成本。

归根结底,管理 0-RTT 重放攻击风险的责任在于应用协议。 使用 QUIC 的应用协议 MUST 描述该协议如何使用 0-RTT,以及采用哪些措施来防范重放攻击。对重放风险的分析需要考虑 所有承载应用语义的 QUIC 协议特性。

完全禁用 0-RTT 是抵御重放攻击最有效的防御方式。

QUIC 扩展 MUST 要么描述重放攻击如何影响其操作, 要么禁止在 0-RTT 中使用该扩展。应用协议 MUST 要么禁止在 0-RTT 中使用承载应用语义的扩展,要么提供重放缓解策略。

9.3. 数据包反射攻击缓解

较小的 ClientHello 如果导致服务器产生大块握手消息,可能会在数据包反射 攻击中被用来放大攻击者生成的流量。

QUIC 包含三种针对这种攻击的防御。首先,包含 ClientHello 的数据包 MUST 被填充到最小大小。其次,如果响应未经验证的源地址, 服务器被禁止发送超过其已接收字节数三倍的字节(见 第 8.1 节, [QUIC-TRANSPORT])。最后,由于 Handshake 数据包的确认经过认证,盲攻击者无法伪造它们。综合来看,这些防御 限制了放大程度。

9.4. 标头保护分析

[NAN] 分析了提供 nonce 隐私的认证加密算法,称为 “Hide Nonce”(HN)变换。 本文档中的通用标头保护构造是这些算法之一(HN1)。标头保护在 数据包保护 AEAD 之后应用,从 AEAD 输出中采样一组字节(sample), 并使用伪随机函数(PRF)按如下方式加密标头字段:

protected_field = field XOR PRF(hp_key, sample)

本文档中的标头保护变体使用伪随机置换(PRP)来代替通用 PRF。 然而,由于所有 PRP 也是 PRF [IMC], 这些变体并未偏离 HN1 构造。

由于 hp_key 不同于数据包保护密钥,因此 标头保护实现了 [NAN] 中定义的 AE2 安全性,并因此保证 field(受保护数据包标头)的隐私。未来基于此构造的标头保护 变体 MUST 使用 PRF,以确保等价的安全保证。

多次使用相同的密钥和密文样本会有损害标头保护的风险。 使用相同密钥和密文样本保护两个不同标头,会暴露受保护字段的异或值。 假设 AEAD 表现为 PRF,如果采样 L 位,则两个密文样本相同的概率接近 2-L/2,也就是生日界。对于本文档描述的算法,该概率为 264 分之一。

为防止攻击者修改数据包标头,标头通过数据包保护被传递性认证; 整个数据包标头都是经认证附加数据的一部分。被伪造或修改的受保护字段 只有在数据包保护被移除后才能检测到。

9.5. 标头保护计时侧信道

攻击者可能猜测数据包号或 Key Phase 的值,并让端点通过计时侧信道 确认这些猜测。同样,也可以尝试并暴露对数据包号长度的猜测。如果数据包接收方 在不尝试移除数据包保护的情况下丢弃具有重复数据包号的数据包,它们可能会通过 计时侧信道泄露该数据包号与已接收数据包相匹配。为了使认证不含侧信道, 标头保护移除、数据包号恢复和数据包保护移除的整个过程 MUST 一起应用,并且不能有计时和其他侧信道。

发送数据包时,数据包载荷和数据包号的构造与保护 MUST 不得包含会泄露数据包号或其编码大小的侧信道。

在密钥更新期间,生成新密钥所花费的时间可能会通过计时侧信道暴露 密钥更新已经发生。或者,在攻击者注入数据包的场景下,该侧信道可能会泄露 注入数据包上的 Key Phase 值。收到密钥更新后,端点 SHOULD 生成并保存下一组接收数据包保护密钥,如 第 6.3 节 所述。通过在收到密钥更新之前生成新密钥,接收数据包不会产生泄露 Key Phase 值的计时信号。

这依赖于不在数据包处理期间进行密钥生成,并且可能要求端点为接收 维护三组数据包保护密钥:上一密钥阶段、当前密钥阶段和下一密钥阶段。 端点也可以选择推迟生成下一组接收数据包保护密钥,直到丢弃旧密钥, 这样在任意时刻只需保留两组接收密钥。

9.6. 密钥多样性

在使用 TLS 时,会使用 TLS 的中心密钥调度。由于 TLS 握手消息被整合到机密计算中,包含 QUIC 传输参数扩展可确保握手 和 1-RTT 密钥不同于运行 TCP 上 TLS 的服务器可能产生的密钥。 为避免跨协议密钥同步的可能性,还提供了附加措施来改进密钥分离。

QUIC 数据包保护密钥和 IV 使用与 TLS 中等价密钥不同的标签 派生。

为保持这种分离,QUIC 的新版本 SHOULD 为数据包保护密钥和 IV 以及标头保护密钥的密钥派生定义新标签。此 QUIC 版本使用字符串 “quic”。 其他版本可以使用版本特定标签来代替该字符串。

Initial 机密使用特定于协商出的 QUIC 版本的密钥。 新的 QUIC 版本 SHOULD 定义用于计算 Initial 机密的新 salt 值。

9.7. 随机性

QUIC 依赖端点能够生成安全随机数,既直接用于连接 ID 等协议值, 也通过 TLS 间接使用。关于安全随机数生成的指南,见 [RFC4086]

10. IANA 考虑

IANA 已在 “TLS ExtensionType Values” 注册表 [TLS-REGISTRIES] 中,为 quic_transport_parameters 扩展 (定义于 第 8.2 节)注册了码点 57 (即 0x39)。

此扩展的 Recommended 列标记为 Yes。TLS 1.3 列包含 CH(ClientHello)和 EE(EncryptedExtensions)。

表 2TLS ExtensionType Values 注册表 条目
扩展名称 TLS 1.3 推荐 引用
57 quic_transport_parameters CH, EE Y 本文档

11. 参考文献

11.1. 规范性引用

[AEAD]
McGrew, D., “认证加密的接口和算法”, RFC 5116, DOI 10.17487/RFC5116, , <https://www.rfc-editor.org/info/rfc5116>.
[AES]
“高级加密标准(AES)”, National Institute of Standards and Technology report, DOI 10.6028/nist.fips.197, , <https://doi.org/10.6028/nist.fips.197>.
[ALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, “传输层安全性(TLS)应用层协议协商 扩展”, RFC 7301, DOI 10.17487/RFC7301, , <https://www.rfc-editor.org/info/rfc7301>.
[CHACHA]
Nir, Y. and A. Langley, “用于 IETF 协议的 ChaCha20 和 Poly1305”, RFC 8439, DOI 10.17487/RFC8439, , <https://www.rfc-editor.org/info/rfc8439>.
[HKDF]
Krawczyk, H. and P. Eronen, “基于 HMAC 的提取与扩展密钥派生函数(HKDF)”, RFC 5869, DOI 10.17487/RFC5869, , <https://www.rfc-editor.org/info/rfc5869>.
[QUIC-RECOVERY]
Iyengar, J., Ed. and I. Swett, Ed., “QUIC 丢包检测和拥塞控制”, RFC 9002, DOI 10.17487/RFC9002, , <https://www.rfc-editor.org/info/rfc9002>.
[QUIC-TRANSPORT]
Iyengar, J., Ed. and M. Thomson, Ed., “QUIC:一种基于 UDP 的多路复用安全传输”, RFC 9000, DOI 10.17487/RFC9000, , <https://www.rfc-editor.org/info/rfc9000>.
[RFC2119]
Bradner, S., “RFC 中用于表示要求级别的关键词”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC4086]
Eastlake 3rd, D., Schiller, J., and S. Crocker, “安全性的随机性要求”, BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
[RFC8174]
Leiba, B., “RFC 2119 关键词中大写与 小写的歧义”, BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[SHA]
Dang, Q., “安全哈希标准”, National Institute of Standards and Technology report, DOI 10.6028/nist.fips.180-4, , <https://doi.org/10.6028/nist.fips.180-4>.
[TLS-REGISTRIES]
Salowey, J. and S. Turner, “TLS 和 DTLS 的 IANA 注册表更新”, RFC 8447, DOI 10.17487/RFC8447, , <https://www.rfc-editor.org/info/rfc8447>.
[TLS13]
Rescorla, E., “传输层安全性 (TLS)协议版本 1.3”, RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/info/rfc8446>.

11.2. 资料性引用

[AEBounds]
Luykx, A. and K. Paterson, “TLS 中认证加密使用的限制”, , <https://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf>.
[ASCII]
Cerf, V., “用于网络交换的 ASCII 格式”, STD 80, RFC 20, DOI 10.17487/RFC0020, , <https://www.rfc-editor.org/info/rfc20>.
[CCM-ANALYSIS]
Jonsson, J., “关于 CTR + CBC-MAC 的安全性”, Selected Areas in Cryptography, SAC 2002, Lecture Notes in Computer Science, vol 2595, pp. 76-93, DOI 10.1007/3-540-36492-7_7, , <https://doi.org/10.1007/3-540-36492-7_7>.
[COMPRESS]
Ghedini, A. and V. Vasiliev, “TLS 证书压缩”, RFC 8879, DOI 10.17487/RFC8879, , <https://www.rfc-editor.org/info/rfc8879>.
[GCM-MU]
Hoang, V., Tessaro, S., and A. Thiruvengadam, “重新审视 GCM 的多用户安全性: Nonce 随机化的紧界”, CCS '18: Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pp. 1429-1440, DOI 10.1145/3243734.3243816, , <https://doi.org/10.1145/3243734.3243816>.
[HTTP-REPLAY]
Thomson, M., Nottingham, M., and W. Tarreau, “在 HTTP 中使用 Early Data”, RFC 8470, DOI 10.17487/RFC8470, , <https://www.rfc-editor.org/info/rfc8470>.
[HTTP2-TLS13]
Benjamin, D., “将 TLS 1.3 与 HTTP/2 一起使用”, RFC 8740, DOI 10.17487/RFC8740, , <https://www.rfc-editor.org/info/rfc8740>.
[IMC]
Katz, J. and Y. Lindell, “现代密码学导论,第二版”, ISBN 978-1466570269, .
[NAN]
Bellare, M., Ng, R., and B. Tackmann, “Nonces Are Noticed:重新审视 AEAD”, Advances in Cryptology - CRYPTO 2019, Lecture Notes in Computer Science, vol 11692, pp. 235-265, DOI 10.1007/978-3-030-26948-7_9, , <https://doi.org/10.1007/978-3-030-26948-7_9>.
[QUIC-HTTP]
Bishop, M., Ed., “超文本传输协议 版本 3(HTTP/3)”, 进行中的工作, Internet-Draft, draft-ietf-quic-http-34, , <https://tools.ietf.org/html/draft-ietf-quic-http-34>.
[RFC2818]
Rescorla, E., “HTTP over TLS”, RFC 2818, DOI 10.17487/RFC2818, , <https://www.rfc-editor.org/info/rfc2818>.
[RFC5280]
Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, “互联网 X.509 公钥基础设施证书和证书 吊销列表(CRL)配置文件”, RFC 5280, DOI 10.17487/RFC5280, , <https://www.rfc-editor.org/info/rfc5280>.
[ROBUST]
Fischlin, M., Günther, F., and C. Janson, “健壮信道:在 QUIC 和 DTLS 1.3 记录层中处理不可靠网络”, , <https://eprint.iacr.org/2020/718>.

附录 A. 示例数据包保护

本节展示数据包保护示例,使实现可以逐步验证。定义了来自客户端和服务器的 Initial 数据包样本,以及一个 Retry 数据包。这些数据包使用一个由客户端选择的 8 字节 Destination Connection ID:0x8394c8f03e515708。包含了一些中间值。 所有值均以十六进制显示。

A.1. 密钥

HKDF-Expand-Label 函数执行期间生成的标签 (即 HkdfLabel.label),以及为了产生输出而提供给 HKDF-Expand 函数的部分值如下:

client in:

00200f746c73313320636c69656e7420696e00

server in:

00200f746c7331332073657276657220696e00

quic key:

00100e746c7331332071756963206b657900

quic iv:

000c0d746c733133207175696320697600

quic hp:

00100d746c733133207175696320687000

Initial 机密是公共的:

initial_secret = HKDF-Extract(initial_salt, cid)
    = 7db5df06e7a69e432496adedb0085192
      3595221596ae2ae9fb8115c1e9ed0a44

用于保护客户端数据包的机密如下:

client_initial_secret
    = HKDF-Expand-Label(initial_secret, "client in", "", 32)
    = c00cf151ca5be075ed0ebfb5c80323c4
      2d6b7db67881289af4008f1f6c357aea

key = HKDF-Expand-Label(client_initial_secret, "quic key", "", 16)
    = 1f369613dd76d5467730efcbe3b1a22d

iv  = HKDF-Expand-Label(client_initial_secret, "quic iv", "", 12)
    = fa044b2f42a3fd3b46fb255c

hp  = HKDF-Expand-Label(client_initial_secret, "quic hp", "", 16)
    = 9f50449e04a0e810283a1e9933adedd2

用于保护服务器数据包的机密如下:

server_initial_secret
    = HKDF-Expand-Label(initial_secret, "server in", "", 32)
    = 3c199828fd139efd216c155ad844cc81
      fb82fa8d7446fa7d78be803acdda951b

key = HKDF-Expand-Label(server_initial_secret, "quic key", "", 16)
    = cf3a5331653c364c88f0f379b6067e37

iv  = HKDF-Expand-Label(server_initial_secret, "quic iv", "", 12)
    = 0ac1493ca1905853b0bba03e

hp  = HKDF-Expand-Label(server_initial_secret, "quic hp", "", 16)
    = c206b8d9b9f0f37644430b490eeaa314

A.2. 客户端 Initial

客户端发送一个 Initial 数据包。该数据包的未受保护载荷包含以下 CRYPTO 帧,以及足够的 PADDING 帧,以构成 1162 字节载荷:

060040f1010000ed0303ebf8fa56f129 39b9584a3896472ec40bb863cfd3e868
04fe3a47f06a2b69484c000004130113 02010000c000000010000e00000b6578
616d706c652e636f6dff01000100000a 00080006001d00170018001000070005
04616c706e0005000501000000000033 00260024001d00209370b2c9caa47fba
baf4559fedba753de171fa71f50f1ce1 5d43e994ec74d748002b000302030400
0d0010000e0403050306030203080408 050806002d00020101001c0002400100
3900320408ffffffffffffffff050480 00ffff07048000ffff08011001048000
75300901100f088394c8f03e51570806 048000ffff

未受保护标头指示长度为 1182 字节:4 字节数据包号、1162 字节帧 和 16 字节认证标签。该标头包含连接 ID 和数据包号 2:

c300000001088394c8f03e5157080000449e00000002

保护载荷会产生用于标头保护采样的输出。由于标头使用 4 字节数据包号编码, 因此会对受保护载荷的前 16 字节进行采样,然后按如下方式应用到标头:

sample = d1b1c98dd7689fb8ec11d242b123dc9b

mask = AES-ECB(hp, sample)[0..4]
     = 437b9aec36

header[0] ^= mask[0] & 0x0f
     = c0
header[18..21] ^= mask[1..4]
     = 7b9aec34
header = c000000001088394c8f03e5157080000449e7b9aec34

所得受保护数据包如下:

c000000001088394c8f03e5157080000 449e7b9aec34d1b1c98dd7689fb8ec11
d242b123dc9bd8bab936b47d92ec356c 0bab7df5976d27cd449f63300099f399
1c260ec4c60d17b31f8429157bb35a12 82a643a8d2262cad67500cadb8e7378c
8eb7539ec4d4905fed1bee1fc8aafba1 7c750e2c7ace01e6005f80fcb7df6212
30c83711b39343fa028cea7f7fb5ff89 eac2308249a02252155e2347b63d58c5
457afd84d05dfffdb20392844ae81215 4682e9cf012f9021a6f0be17ddd0c208
4dce25ff9b06cde535d0f920a2db1bf3 62c23e596d11a4f5a6cf3948838a3aec
4e15daf8500a6ef69ec4e3feb6b1d98e 610ac8b7ec3faf6ad760b7bad1db4ba3
485e8a94dc250ae3fdb41ed15fb6a8e5 eba0fc3dd60bc8e30c5c4287e53805db
059ae0648db2f64264ed5e39be2e20d8 2df566da8dd5998ccabdae053060ae6c
7b4378e846d29f37ed7b4ea9ec5d82e7 961b7f25a9323851f681d582363aa5f8
9937f5a67258bf63ad6f1a0b1d96dbd4 faddfcefc5266ba6611722395c906556
be52afe3f565636ad1b17d508b73d874 3eeb524be22b3dcbc2c7468d54119c74
68449a13d8e3b95811a198f3491de3e7 fe942b330407abf82a4ed7c1b311663a
c69890f4157015853d91e923037c227a 33cdd5ec281ca3f79c44546b9d90ca00
f064c99e3dd97911d39fe9c5d0b23a22 9a234cb36186c4819e8b9c5927726632
291d6a418211cc2962e20fe47feb3edf 330f2c603a9d48c0fcb5699dbfe58964
25c5bac4aee82e57a85aaf4e2513e4f0 5796b07ba2ee47d80506f8d2c25e50fd
14de71e6c418559302f939b0e1abd576 f279c4b2e0feb85c1f28ff18f58891ff
ef132eef2fa09346aee33c28eb130ff2 8f5b766953334113211996d20011a198
e3fc433f9f2541010ae17c1bf202580f 6047472fb36857fe843b19f5984009dd
c324044e847a4f4a0ab34f719595de37 252d6235365e9b84392b061085349d73
203a4a13e96f5432ec0fd4a1ee65accd d5e3904df54c1da510b0ff20dcc0c77f
cb2c0e0eb605cb0504db87632cf3d8b4 dae6e705769d1de354270123cb11450e
fc60ac47683d7b8d0f811365565fd98c 4c8eb936bcab8d069fc33bd801b03ade
a2e1fbc5aa463d08ca19896d2bf59a07 1b851e6c239052172f296bfb5e724047
90a2181014f3b94a4e97d117b4381303 68cc39dbb2d198065ae3986547926cd2
162f40a29f0c3c8745c0f50fba3852e5 66d44575c29d39a03f0cda721984b6f4
40591f355e12d439ff150aab7613499d bd49adabc8676eef023b15b65bfc5ca0
6948109f23f350db82123535eb8a7433 bdabcb909271a6ecbcb58b936a88cd4e
8f2e6ff5800175f113253d8fa9ca8885 c2f552e657dc603f252e1a8e308f76f0
be79e2fb8f5d5fbbe2e30ecadd220723 c8c0aea8078cdfcb3868263ff8f09400
54da48781893a7e49ad5aff4af300cd8 04a6b6279ab3ff3afb64491c85194aab
760d58a606654f9f4400e8b38591356f bf6425aca26dc85244259ff2b19c41b9
f96f3ca9ec1dde434da7d2d392b905dd f3d1f9af93d1af5950bd493f5aa731b4
056df31bd267b6b90a079831aaf579be 0a39013137aac6d404f518cfd4684064
7e78bfe706ca4cf5e9c5453e9f7cfd2b 8b4c8d169a44e55c88d4a9a7f9474241
e221af44860018ab0856972e194cd934

A.3. 服务器 Initial

服务器发送以下载荷作为响应,其中包含 ACK 帧、CRYPTO 帧, 且不含 PADDING 帧:

02000000000600405a020000560303ee fce7f7b37ba1d1632e96677825ddf739
88cfc79825df566dc5430b9a045a1200 130100002e00330024001d00209d3c94
0d89690b84d08a60993c144eca684d10 81287c834d5311bcf32bb9da1a002b00
020304

来自服务器的标头包含一个新的连接 ID,并为数据包号 1 使用 2 字节数据包号编码:

c1000000010008f067a5502a4262b50040750001

因此,在保护之后,标头保护样本从第三个受保护字节开始取得:

sample = 2cd0991cd25b0aac406a5816b6394100
mask   = 2ec0d8356a
header = cf000000010008f067a5502a4262b5004075c0d9

最终的受保护数据包如下:

cf000000010008f067a5502a4262b500 4075c0d95a482cd0991cd25b0aac406a
5816b6394100f37a1c69797554780bb3 8cc5a99f5ede4cf73c3ec2493a1839b3
dbcba3f6ea46c5b7684df3548e7ddeb9 c3bf9c73cc3f3bded74b562bfb19fb84
022f8ef4cdd93795d77d06edbb7aaf2f 58891850abbdca3d20398c276456cbc4
2158407dd074ee

A.4. Retry

这里展示了一个可能为响应 附录 A.2 中 Initial 数据包而发送的 Retry 数据包。完整性检查包含客户端选择的 连接 ID 值 0x8394c8f03e515708,但该值不包含在最终的 Retry 数据包中:

ff000000010008f067a5502a4262b574 6f6b656e04a265ba2eff4d829058fb3f
0f2496ba

A.5. ChaCha20-Poly1305 短标头数据包

此示例展示了保护短标头数据包所需的一些步骤。 此示例使用 AEAD_CHACHA20_POLY1305。

在此示例中,TLS 产生一个 application write secret,服务器从中 使用 HKDF-Expand-Label 产生四个值:密钥、IV、标头保护密钥,以及 密钥更新后将使用的机密(最后这个值在此示例中不再使用)。

secret
    = 9ac312a7f877468ebe69422748ad00a1
      5443f18203a07d6060f688f30f21632b

key = HKDF-Expand-Label(secret, "quic key", "", 32)
    = c6d98ff3441c3fe1b2182094f69caa2e
      d4b716b65488960a7a984979fb23e1c8

iv  = HKDF-Expand-Label(secret, "quic iv", "", 12)
    = e0459b3474bdd0e44a41c144

hp  = HKDF-Expand-Label(secret, "quic hp", "", 32)
    = 25a282b9e82f06f21f488917a4fc8f1b
      73573685608597d0efcb076b0ab7a7a4

ku  = HKDF-Expand-Label(secret, "quic ku", "", 32)
    = 1223504755036d556342ee9361d25342
      1a826c9ecdf3c7148684b36b714881f9

下面展示了保护一个具有空 Destination Connection ID 的最小数据包 所涉及的步骤。此数据包包含单个 PING 帧(即载荷仅为 0x01), 数据包号为 654360564。在此示例中,使用长度为 3 的数据包号 (即编码 49140)避免了必须填充数据包载荷;如果数据包号编码在更少字节上, 则需要 PADDING 帧。

pn                 = 654360564 (decimal)
nonce              = e0459b3474bdd0e46d417eb0
unprotected header = 4200bff4
payload plaintext  = 01
payload ciphertext = 655e5cd55c41f69080575d7999c25a5bfb

所得密文是可能的最小大小。会跳过一个字节来产生标头保护样本。

sample = 5e5cd55c41f69080575d7999c25a5bfb
mask   = aefefe7d03
header = 4cfe4189

受保护数据包是 21 字节的最小可能数据包大小。

packet = 4cfe4189655e5cd55c41f69080575d7999c25a5bfb

附录 B. AEAD 算法分析

本节记录用于推导 AEAD_AES_128_GCM、AEAD_AES_128_CCM 和 AEAD_AES_256_GCM 的 AEAD 算法限制的分析。以下分析使用符号表示乘法(*)、 除法(/)和指数(^),并使用括号建立优先级。还使用以下符号:

t:

认证标签的位大小。对于这些密码,t 为 128。

n:

分组函数的位大小。对于这些密码,n 为 128。

k:

密钥的位大小。AEAD_AES_128_GCM 和 AEAD_AES_128_CCM 为 128;AEAD_AES_256_GCM 为 256。

l:

每个数据包中的块数(见下文)。

q:

端点创建并保护的真实数据包数量。该值是更新密钥之前 可以保护的数据包数量上界。

v:

端点将接受的伪造数据包数量。该值是端点在更新密钥之前 可以拒绝的伪造数据包数量上界。

o:

对手进行的离线理想密码查询数量。

以下分析依赖于生成每条消息所涉及的分组操作数量的计数。 该分析针对最大为 211(l = 27)和 216(l = 212)的数据包大小执行。211 的大小预计是匹配 常见部署模式的限制,而 216 是 QUIC 数据包的最大可能 大小。只有严格限制数据包大小的端点,才能使用通过较小数据包大小推导出的 更大的机密性和完整性限制。

对于 AEAD_AES_128_GCM 和 AEAD_AES_256_GCM,消息长度(l)是 关联数据长度(以块计)加上明文长度(以块计)。

对于 AEAD_AES_128_CCM,分组密码操作总数是以下各项之和: 关联数据长度(以块计)、密文长度(以块计)、明文长度(以块计),再加 1。 在此分析中,这被简化为数据包块长度两倍的值(即,对于限制为 211 字节的数据包,2l = 28;否则为 2l = 213)。此简化基于数据包包含所有关联数据和 密文。这会导致每个数据包的操作数高估一到三个块。

B.1. AEAD_AES_128_GCM 和 AEAD_AES_256_GCM 使用限制分析

[GCM-MU] 指定了 AEAD_AES_128_GCM 和 AEAD_AES_256_GCM 在 TLS 1.3 和 QUIC 中使用时的具体界。本节使用几个简化假设来记录该分析:

  • 攻击者在伪造尝试中使用的密文块数量 由 v * l 限定,即伪造尝试次数乘以每个数据包的大小(以块计)。
  • 攻击者完成的离线工作量在分析中不支配其他因素。

[GCM-MU] 中的界比 [AEBounds] 中使用的界更紧且更完整, 这允许使用比 [TLS13] 中描述的限制更大的限制。

B.1.1. 机密性限制

对于机密性,[GCM-MU] 中的定理 (4.3) 表明,对于一个不重复 nonce 的 单个用户,决定攻击者在区分真实 AEAD 算法和随机 AEAD 算法时获得优势的 主导项是:

2 * (q * l)^2 / 2^n

对于 2-57 的目标优势,这会产生以下关系:

q <= 2^35 / l

因此,不发送大于 211 字节的数据包的端点, 在单个连接中不能保护超过 228 个数据包,否则会使攻击者获得 比 2-57 目标更显著的优势。允许数据包大小达到 216 的端点,其限制则为 223

B.1.2. 完整性限制

对于完整性,[GCM-MU] 中的定理 (4.3) 表明,攻击者成功伪造 一个数据包所获得的优势不超过以下值:

(1 / 2^(8 * n)) + ((2 * v) / 2^(2 * n))
        + ((2 * o * v) / 2^(k + n)) + (n * (v + (v * l)) / 2^k)

目标是将此优势限制为 2-57。对于 AEAD_AES_128_GCM, 该不等式中的第四项支配其余项,因此可在不显著影响结果的情况下 移除其他项。这会产生以下近似:

v <= 2^64 / l

不尝试移除大于 211 字节数据包保护的端点, 最多可以尝试移除 257 个数据包的保护。不限制所处理数据包 大小的端点,最多可以尝试移除 252 个数据包的保护。

对于 AEAD_AES_256_GCM,同一项仍然支配,但更大的 k 值 会产生以下近似:

v <= 2^192 / l

这明显大于 AEAD_AES_128_GCM 的限制。然而,本文档建议 对两个函数应用相同限制,因为任一限制都足够大。

B.2. AEAD_AES_128_CCM 使用限制分析

TLS [TLS13][AEBounds] 未指定 AEAD_AES_128_CCM 的使用限制。然而,任何与 QUIC 一起使用的 AEAD 都需要 使用限制,以确保同时保留机密性和完整性。本节记录该分析。

[CCM-ANALYSIS] 被用作此分析的基础。该分析的结果用于推导基于 [TLS13] 中所选限制的使用限制。

对于机密性,[CCM-ANALYSIS] 中的定理 2 表明,攻击者 相对于理想伪随机置换(PRP)获得的区分优势不超过以下值:

(2l * q)^2 / 2^n

[CCM-ANALYSIS] 中定理 1 的完整性限制,在消息数量相同的情况下 为攻击者提供严格更高的优势。由于机密性优势和完整性优势的目标相同, 只需考虑定理 1。

定理 1 表明,攻击者相对于理想 PRP 获得的优势不超过以下值:

v / 2^t + (2l * (v + q))^2 / 2^n

由于 tn 都是 128,第一项相对于 第二项可以忽略,因此可在不显著影响结果的情况下移除该项。

这会产生一种关系,将加密和解密尝试与仅由机密性定理产生的相同限制 结合起来。对于 2-57 的目标优势,会得到以下结果:

v + q <= 2^34.5 / l

通过设置 q = v,可以产生机密性和完整性限制的值。 因此,将数据包限制为 211 字节的端点,其机密性和完整性限制 均为 226.5 个数据包。不限制数据包大小的端点的限制为 221.5

贡献者

IETF QUIC 工作组得到了许多人的巨大支持。以下人员为本文档提供了 实质性贡献:

作者地址

Martin Thomson (编辑)
Mozilla
Sean Turner (编辑)
sn3rd