互联网工程任务组 (IETF)                                    E. Rescorla
征求意见稿:8446                                                Mozilla
废止:507752466961                         2018 年 8 月
更新:57056066
类别:标准化进程
ISSN: 2070-1721


        传输层安全性(TLS)协议版本 1.3

摘要

   本文档规定了传输层安全性(TLS)协议的 1.3 版本。
   TLS 允许客户端/服务器应用程序通过互联网通信,其设计目标是
   防止窃听、篡改和消息伪造。

   本文档更新 RFC 5705 和 RFC 6066,并废止 RFC 5077、RFC
   5246 和 RFC 6961。本文档还为 TLS 1.2 实现规定了新的要求。

本备忘录状态

   本文档是互联网标准化进程文档。

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

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

















Rescorla                     标准化进程                       [第 1 页]


RFC 8446                           TLS                       2018 年 8 月


Copyright Notice

   Copyright (c) 2018 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (https://trustee.ietf.org/license-info) in effect on the date of
   publication of this document.  Please review these documents
   carefully, as they describe your rights and restrictions with respect
   to this document.  Code Components extracted from this document must
   include Simplified BSD License text as described in Section 4.e of
   the Trust Legal Provisions and are provided without warranty as
   described in the Simplified BSD License.

   This document may contain material from IETF Documents or IETF
   Contributions published or made publicly available before November
   10, 2008.  The person(s) controlling the copyright in some of this
   material may not have granted the IETF Trust the right to allow
   modifications of such material outside the IETF Standards Process.
   Without obtaining an adequate license from the person(s) controlling
   the copyright in such materials, this document may not be modified
   outside the IETF Standards Process, and derivative works of it may
   not be created outside the IETF Standards Process, except to format
   it for publication as an RFC or to translate it into languages other
   than English.

























Rescorla                     标准化进程                       [第 2 页]


RFC 8446                           TLS                       2018 年 8 月


目录

   1. 引言 ........................................................6
      1.1. 约定和术语 ..............................................7
      1.2. 与 TLS 1.2 的主要差异 .................................8
      1.3. 影响 TLS 1.2 的更新 ...................................9
   2. 协议概述 ...................................................10
      2.1. 不正确的 DHE 份额 .....................................14
      2.2. 恢复和预共享密钥(PSK) ..............................15
      2.3. 0-RTT 数据 ............................................17
   3. 表示语言 ...................................................19
      3.1. 基本块大小 ............................................19
      3.2. 其他事项 ..............................................20
      3.3. 数字 ..................................................20
      3.4. 向量 ..................................................20
      3.5. 枚举 ..................................................21
      3.6. 构造类型 ..............................................22
      3.7. 常量 ..................................................23
      3.8. 变体 ..................................................23
   4. 握手协议 ...................................................24
      4.1. 密钥交换消息 ..........................................25
           4.1.1. 密码协商 ......................................26
           4.1.2. Client Hello ...................................27
           4.1.3. Server Hello ...................................31
           4.1.4. Hello Retry Request ...........................33
      4.2. 扩展 ..................................................35
           4.2.1. Supported Versions ............................39
           4.2.2. Cookie ........................................40
           4.2.3. Signature Algorithms ..........................41
           4.2.4. Certificate Authorities .......................45
           4.2.5. OID Filters ...................................45
           4.2.6. 握手后客户端认证 .............................47
           4.2.7. Supported Groups ..............................47
           4.2.8. Key Share .....................................48
           4.2.9. Pre-Shared Key Exchange Modes .................51
           4.2.10. Early Data Indication ........................52
           4.2.11. Pre-Shared Key Extension .....................55
      4.3. 服务器参数 ............................................59
           4.3.1. Encrypted Extensions ..........................60
           4.3.2. Certificate Request ...........................60
      4.4. 认证消息 ..............................................61
           4.4.1. Transcript Hash ...............................63
           4.4.2. Certificate ...................................64
           4.4.3. Certificate Verify ............................69
           4.4.4. Finished ......................................71
      4.5. Early Data 结束 .......................................72





Rescorla                     标准化进程                       [第 3 页]


RFC 8446                           TLS                       2018 年 8 月


      4.6. 握手后消息 ............................................73
           4.6.1. New Session Ticket Message ....................73
           4.6.2. 握手后认证 ...................................75
           4.6.3. 密钥和初始化向量更新 .........................76
   5. 记录协议 ...................................................77
      5.1. 记录层 ................................................78
      5.2. 记录载荷保护 ..........................................80
      5.3. 每记录 Nonce ...........................................82
      5.4. 记录填充 ..............................................83
      5.5. 密钥使用限制 ..........................................84
   6. 告警协议 ...................................................85
      6.1. 关闭告警 ..............................................87
      6.2. 错误告警 ..............................................88
   7. 密码计算 ...................................................90
      7.1. 密钥调度 ..............................................91
      7.2. 更新流量秘密值 ........................................94
      7.3. 流量密钥计算 ..........................................95
      7.4. (EC)DHE 共享秘密计算 ..................................95
           7.4.1. 有限域 Diffie-Hellman .........................95
           7.4.2. 椭圆曲线 Diffie-Hellman ......................96
      7.5. 导出器 ................................................97
   8. 0-RTT 与抗重放 .............................................98
      8.1. 一次性票据 ............................................99
      8.2. Client Hello 记录 ......................................99
      8.3. 新鲜性检查 ...........................................101
   9. 合规要求 ..................................................102
      9.1. 必须实现的密码套件 ...................................102
      9.2. 必须实现的扩展 .......................................103
      9.3. 协议不变式 ...........................................104
   10. 安全考虑 ................................................106
   11. IANA 考虑 ...............................................106
   12. 参考文献 ................................................109
      12.1. 规范性参考文献 .....................................109
      12.2. 资料性参考文献 .....................................112
   附录 A. 状态机 ...............................................120
     A.1. 客户端 ................................................120
     A.2. 服务器 ................................................121
   附录 B. 协议数据结构和常量值 .................................122
     B.1. 记录层 ................................................122
     B.2. 告警消息 ..............................................123
     B.3. 握手协议 ..............................................124
       B.3.1. 密钥交换消息 .....................................125
       B.3.2. 服务器参数消息 ...................................131
       B.3.3. 认证消息 .........................................132
       B.3.4. 票据建立 .........................................132
       B.3.5. 更新密钥 .........................................133
     B.4. 密码套件 ..............................................133




Rescorla                     标准化进程                       [第 4 页]


RFC 8446                           TLS                       2018 年 8 月


   附录 C. 实现说明 .............................................134
     C.1. 随机数生成和播种 .....................................134
     C.2. 证书和认证 ...........................................135
     C.3. 实现陷阱 .............................................135
     C.4. 客户端跟踪防护 .......................................137
     C.5. 未认证操作 ...........................................137
   附录 D. 向后兼容性 ...........................................138
     D.1. 与旧服务器协商 .......................................139
     D.2. 与旧客户端协商 .......................................139
     D.3. 0-RTT 向后兼容性 .....................................140
     D.4. 中间盒兼容模式 .......................................140
     D.5. 与向后兼容性有关的安全限制 ...........................141
   附录 E. 安全属性概述 .........................................142
     E.1. 握手 .................................................142
       E.1.1. 密钥派生和 HKDF ..................................145
       E.1.2. 客户端认证 .......................................146
       E.1.3. 0-RTT ............................................146
       E.1.4. 导出器独立性 .....................................146
       E.1.5. 泄露后安全性 .....................................146
       E.1.6. 外部参考 .........................................147
     E.2. 记录层 ...............................................147
       E.2.1. 外部参考 .........................................148
     E.3. 流量分析 .............................................148
     E.4. 侧信道攻击 ...........................................149
     E.5. 对 0-RTT 的重放攻击 ..................................150
       E.5.1. 重放和导出器 .....................................151
     E.6. PSK 身份暴露 .........................................152
     E.7. 共享 PSK .............................................152
     E.8. 对静态 RSA 的攻击 ....................................152
   贡献者 .......................................................153
   作者地址 .....................................................160




















Rescorla                     标准化进程                       [第 5 页]


RFC 8446                           TLS                       2018 年 8 月


1.  引言

   TLS 的主要目标是在两个通信对等方之间提供安全信道;底层
   传输唯一需要满足的要求是可靠、有序的数据流。具体而言,
   安全信道应提供以下属性:

   -  认证:信道的服务器端始终会被认证;客户端可选择性地
      被认证。认证可以通过非对称密码术(例如 RSA
      [RSA]、椭圆曲线数字签名算法(ECDSA)
      [ECDSA],或 Edwards 曲线数字签名算法(EdDSA)
      [RFC8032])或对称预共享密钥(PSK)来完成。

   -  机密性:信道建立之后通过信道发送的数据仅对端点可见。
      TLS 不隐藏其传输数据的长度,不过端点能够对 TLS 记录
      进行填充,以便混淆长度并提高对流量分析技术的防护。

   -  完整性:信道建立之后通过信道发送的数据不能被攻击者
      修改而不被检测到。

   即使面对如 [RFC3552] 所述完全控制网络的攻击者,这些属性
   也应成立。关于相关安全属性的更完整陈述,请参见
   附录 E。

   TLS 由两个主要组件组成:

   -  握手协议(第 4 节),它认证通信双方,协商密码模式和
      参数,并建立共享密钥材料。握手协议被设计为能够抵抗篡改;
      主动攻击者不应能够迫使对等方协商出与未受攻击连接中不同的
      参数。

   -  记录协议(第 5 节),它使用握手协议建立的参数来保护
      通信对等方之间的流量。记录协议将流量划分为一系列记录,
      每条记录都使用流量密钥独立保护。








Rescorla                     标准化进程                       [第 6 页]


RFC 8446                           TLS                       2018 年 8 月


   TLS 独立于应用协议;更高层协议可以透明地叠加在 TLS 之上。
   然而,TLS 标准并未规定协议如何使用 TLS 来增加安全性;如何
   发起 TLS 握手以及如何解释交换的认证证书,留给运行在 TLS
   之上的协议的设计者和实现者判断。

   本文档定义 TLS 版本 1.3。虽然 TLS 1.3 不能与先前版本直接
   兼容,但所有 TLS 版本都包含版本机制,使客户端和服务器在双方
   都支持时能够互操作地协商出一个共同版本。

   本文档取代并废止 TLS 的先前版本,包括版本 1.2 [RFC5246]。
   它还废止 [RFC5077] 中定义的 TLS 票据机制,并用
   第 2.2 节中定义的机制取代它。由于 TLS 1.3 改变了密钥派生的
   方式,它按照第 7.5 节所述更新了 [RFC5705]。它还改变了
   在线证书状态协议(OCSP)消息的承载方式,因此更新了
   [RFC6066] 并废止了 [RFC6961],如第 4.4.2.1 节所述。

1.1.  约定和术语

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

   使用以下术语:

   client:发起 TLS 连接的端点。

   connection:两个端点之间的传输层连接。

   endpoint:连接的客户端或服务器。

   handshake:客户端和服务器之间的初始协商,用于建立它们后续
      在 TLS 内交互的参数。

   peer:端点。在讨论某个特定端点时,“peer”指不是讨论主体的
      那个端点。






Rescorla                     标准化进程                       [第 7 页]


RFC 8446                           TLS                       2018 年 8 月


   receiver:正在接收记录的端点。

   sender:正在传输记录的端点。

   server:未发起 TLS 连接的端点。

1.2.  与 TLS 1.2 的主要差异

   以下列出了 TLS 1.2 与 TLS 1.3 之间的主要功能差异。该列表
   并不意图穷尽所有差异,此外还有许多较小差异。

   -  支持的对称加密算法列表已经删去了所有被认为是遗留的
      算法。保留下来的算法全部是带关联数据的认证加密(AEAD)
      算法。密码套件的概念已经改变,将认证和密钥交换机制与
      记录保护算法(包括秘密密钥长度)以及用于密钥派生函数和
      握手消息认证码(MAC)的哈希分离开来。

   -  增加了零往返时间(0-RTT)模式,可为某些应用数据在连接
      建立时节省一个往返,但代价是牺牲某些安全属性。

   -  静态 RSA 和 Diffie-Hellman 密码套件已被移除;所有基于
      公钥的密钥交换机制现在都提供前向保密。

   -  ServerHello 之后的所有握手消息现在都被加密。新引入的
      EncryptedExtensions 消息使此前以明文形式在 ServerHello 中
      发送的各种扩展也能获得机密性保护。

   -  密钥派生函数已经重新设计。新的设计因改进了密钥分离属性,
      使密码学家更容易分析。基于 HMAC 的 Extract-and-Expand
      Key Derivation Function(HKDF)被用作底层原语。

   -  握手状态机已被大幅重构,以便更加一致,并移除多余消息,
      例如 ChangeCipherSpec(为中间盒兼容性所需时除外)。

   -  椭圆曲线算法现在包含在基础规范中,并包含了新的签名算法,
      例如 EdDSA。TLS 1.3 移除了点格式协商,改为对每条曲线
      使用单一的点格式。




Rescorla                     标准化进程                       [第 8 页]


RFC 8446                           TLS                       2018 年 8 月


   -  还进行了其他密码学改进,包括将 RSA 填充改为使用 RSA
      概率签名方案(RSASSA-PSS),以及移除压缩、数字签名算法
      (DSA)和自定义临时 Diffie-Hellman(DHE)组。

   -  TLS 1.2 版本协商机制已被弃用,改为扩展中的版本列表。
      这提升了与错误实现版本协商的现有服务器的兼容性。

   -  早期 TLS 版本中的带服务器端状态和不带服务器端状态的会话
      恢复以及基于 PSK 的密码套件,已由一个新的统一 PSK 交换
      取代。

   -  参考文献已适当更新为指向 RFC 的更新版本(例如,RFC 5280
      而不是 RFC 3280)。

1.3.  影响 TLS 1.2 的更新

   本文档定义了若干可选地影响 TLS 1.2 实现的更改,包括那些
   并不同时支持 TLS 1.3 的实现:

   -  第 4.1.3 节描述了版本降级保护机制。

   -  第 4.2.3 节定义了 RSASSA-PSS 签名方案。

   -  “supported_versions” ClientHello 扩展可用于协商要使用的
      TLS 版本,优先于 ClientHello 的 legacy_version 字段。

   -  “signature_algorithms_cert”扩展允许客户端指明它能够在
      X.509 证书中验证哪些签名算法。

   另外,本文档澄清了早期 TLS 版本的一些合规要求;参见
   第 9.3 节Rescorla                     标准化进程                       [第 9 页]


RFC 8446                           TLS                       2018 年 8 月


2.  协议概述

   安全信道所使用的密码参数由 TLS 握手协议产生。TLS 的这个
   子协议由客户端和服务器在首次彼此通信时使用。握手协议允许
   对等方协商协议版本、选择密码算法、可选地彼此认证,并建立
   共享秘密密钥材料。一旦握手完成,对等方就使用已建立的密钥
   来保护应用层流量。

   握手失败或其他协议错误会触发连接终止,在终止之前可选地
   发送告警消息(第 6 节)。

   TLS 支持三种基本密钥交换模式:

   -  (EC)DHE(基于有限域或椭圆曲线的 Diffie-Hellman)

   -  仅 PSK

   -  PSK 与 (EC)DHE




























Rescorla                     标准化进程                      [第 10 页]


RFC 8446                           TLS                       2018 年 8 月


   下方图 1 显示了基本的完整 TLS 握手:

       客户端                                           服务器

密钥 ^ ClientHello
交换 | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     v + pre_shared_key*       -------->
                                                  ServerHello  ^ 密钥
                                                 + key_share*  | 交换
                                            + pre_shared_key*  v
                                        {EncryptedExtensions}  ^  服务器
                                        {CertificateRequest*}  v  参数
                                               {Certificate*}  ^
                                         {CertificateVerify*}  | 认证
                                                   {Finished}  v
                               <--------  [Application Data*]
     ^ {Certificate*}
认证 | {CertificateVerify*}
     v {Finished}              -------->
       [Application Data]      <------->  [Application Data]

              +  表示在前面标注的消息中发送的值得注意的扩展。

              *  表示并非总是发送的可选或取决于情形的
                 消息/扩展。

              {} 表示使用从 [sender]_handshake_traffic_secret
                 派生的密钥保护的消息。

              [] 表示使用从 [sender]_application_traffic_secret_N
                 派生的密钥保护的消息。

               图 1:完整 TLS 握手的消息流

   可以将握手视为具有三个阶段(上图中已标出):

   -  密钥交换:建立共享密钥材料并选择密码参数。此阶段之后的
      所有内容都会被加密。

   -  服务器参数:建立其他握手参数(客户端是否被认证、应用层
      协议支持等)。




Rescorla                     标准化进程                      [第 11 页]


RFC 8446                           TLS                       2018 年 8 月


   -  认证:认证服务器(以及可选地认证客户端),并提供密钥确认和
      握手完整性。

   在密钥交换阶段,客户端发送 ClientHello(第 4.1.2 节)
   消息,其中包含随机 nonce(ClientHello.random);它所提供的
   协议版本;对称密码/HKDF 哈希对列表;一组 Diffie-Hellman
   密钥份额(在“key_share”(第 4.2.8 节)扩展中)、一组
   预共享密钥标签(在“pre_shared_key”(第 4.2.11 节)
   扩展中),或两者兼有;还可能包含其他扩展。为了中间盒兼容性,
   还可能存在其他字段和/或消息。

   服务器处理 ClientHello,并确定该连接适当的密码参数。然后它以
   自己的 ServerHello(第 4.1.3 节)作为响应,其中指明协商出的
   连接参数。ClientHello 与 ServerHello 的组合确定共享密钥。
   如果使用 (EC)DHE 密钥建立,则 ServerHello 包含一个带有服务器
   临时 Diffie-Hellman 份额的“key_share”扩展;服务器的份额
   MUST 与客户端份额之一处于同一组。如果使用 PSK 密钥建立,则
   ServerHello 包含一个“pre_shared_key”扩展,指明选择了客户端
   提供的哪个 PSK。注意,实现可以同时使用 (EC)DHE 和 PSK,在
   这种情况下将提供两个扩展。

   然后,服务器发送两条消息来建立服务器参数:

   EncryptedExtensions:对不需要用于确定密码参数的 ClientHello
      扩展的响应,但特定于单个证书的扩展除外。
      [第 4.3.1 节]

   CertificateRequest:如果需要基于证书的客户端认证,则为该证书
      所需的参数。如果不需要客户端认证,则省略此消息。
      [第 4.3.2 节]













Rescorla                     标准化进程                      [第 12 页]


RFC 8446                           TLS                       2018 年 8 月


   最后,客户端和服务器交换认证消息。每当需要基于证书的认证时,
   TLS 都使用同一组消息。(基于 PSK 的认证是密钥交换的副作用。)
   具体如下:

   Certificate:端点的证书以及任何逐证书扩展。如果服务器不使用
      证书进行认证,服务器会省略此消息;如果服务器未发送
      CertificateRequest(从而指明客户端不应使用证书进行认证),
      客户端会省略此消息。注意,如果使用原始公钥 [RFC7250] 或
      cached information 扩展 [RFC7924],则此消息将不包含证书,
      而是包含与服务器长期密钥相对应的其他某个值。
      [第 4.4.2 节]

   CertificateVerify:使用与 Certificate 消息中公钥相对应的私钥,
      对整个握手进行签名。如果端点不通过证书进行认证,则省略此
      消息。[第 4.4.3 节]

   Finished:覆盖整个握手的 MAC(消息认证码)。此消息提供密钥
      确认,将端点身份绑定到交换的密钥,并且在 PSK 模式下也
      认证握手。[第 4.4.4 节]

   收到服务器的消息后,客户端以自己的认证消息作为响应,即
   Certificate 和 CertificateVerify(如果被请求),以及 Finished。

   此时,握手完成,客户端和服务器派生记录层所需的密钥材料,
   以便交换通过认证加密保护的应用层数据。除第 2.3 节中规定的
   情况外,在发送 Finished 消息之前 MUST NOT 发送 Application
   Data。注意,虽然服务器可以在收到客户端的认证消息之前发送
   Application Data,但此时发送的任何数据当然都发送给了一个
   未认证的对等方。














Rescorla                     标准化进程                      [第 13 页]


RFC 8446                           TLS                       2018 年 8 月


2.1.  不正确的 DHE 份额

   如果客户端没有提供足够的“key_share”扩展(例如,它只包含
   服务器不可接受或不支持的 DHE 或 ECDHE 组),服务器会通过
   HelloRetryRequest 纠正该不匹配,客户端需要使用适当的
   “key_share”扩展重新开始握手,如图 2 所示。如果无法协商出
   共同的密码参数,服务器 MUST 使用适当的告警中止握手。

        客户端                                               服务器

        ClientHello
        + key_share             -------->
                                                  HelloRetryRequest
                                <--------               + key_share
        ClientHello
        + key_share             -------->
                                                        ServerHello
                                                        + key_share
                                              {EncryptedExtensions}
                                              {CertificateRequest*}
                                                     {Certificate*}
                                               {CertificateVerify*}
                                                         {Finished}
                                <--------       [Application Data*]
        {Certificate*}
        {CertificateVerify*}
        {Finished}              -------->
        [Application Data]      <------->        [Application Data]

             图 2:带有不匹配参数的完整握手消息流

   注意:握手 transcript 包含初始的 ClientHello/HelloRetryRequest
   交换;它不会因新的 ClientHello 而重置。

   TLS 还允许对基本握手进行若干优化变体,如以下各节所述。











Rescorla                     标准化进程                      [第 14 页]


RFC 8446                           TLS                       2018 年 8 月


2.2.  恢复和预共享密钥(PSK)

   虽然 TLS PSK 可以在带外建立,但 PSK 也可以在此前连接中建立,
   然后用于建立新的连接(“会话恢复”或使用 PSK“恢复”)。
   一旦握手完成,服务器可以向客户端发送一个 PSK identity,它
   对应于从初始握手派生出的唯一密钥(见第 4.6.1 节)。
   然后,客户端可以在将来的握手中使用该 PSK identity 来协商
   使用相关的 PSK。如果服务器接受该 PSK,则新连接的安全上下文
   会以密码学方式绑定到原始连接,并且从初始握手派生的密钥会
   用来引导密码状态,而不是进行完整握手。在 TLS 1.2 及以下版本
   中,此功能由“session IDs”和“session tickets”[RFC5077] 提供。
   这两种机制在 TLS 1.3 中都已废止。

   PSK 可以与 (EC)DHE 密钥交换一起使用,以便在使用共享密钥的
   同时提供前向保密;也可以单独使用,但代价是应用数据失去
   前向保密。































Rescorla                     标准化进程                      [第 15 页]


RFC 8446                           TLS                       2018 年 8 月


   图 3 显示了一对握手,其中第一个握手建立 PSK,第二个握手使用
   该 PSK:

          客户端                                               服务器

   初始握手:
          ClientHello
          + key_share               -------->
                                                          ServerHello
                                                          + key_share
                                                {EncryptedExtensions}
                                                {CertificateRequest*}
                                                       {Certificate*}
                                                 {CertificateVerify*}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Certificate*}
          {CertificateVerify*}
          {Finished}                -------->
                                    <--------      [NewSessionTicket]
          [Application Data]        <------->      [Application Data]


   后续握手:
          ClientHello
          + key_share*
          + pre_shared_key          -------->
                                                          ServerHello
                                                     + pre_shared_key
                                                         + key_share*
                                                {EncryptedExtensions}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Finished}                -------->
          [Application Data]        <------->      [Application Data]

               图 3:恢复和 PSK 的消息流

   由于服务器通过 PSK 进行认证,它不会发送 Certificate 或
   CertificateVerify 消息。当客户端通过 PSK 提供恢复时,它
   SHOULD 同时向服务器提供“key_share”扩展,以允许服务器在需要时
   拒绝恢复并回退到完整握手。服务器以“pre_shared_key”扩展作为
   响应,以协商使用 PSK 密钥建立,并且可以(如此处所示)以
   “key_share”扩展响应,以进行 (EC)DHE 密钥建立,从而提供前向
   保密。




Rescorla                     标准化进程                      [第 16 页]


RFC 8446                           TLS                       2018 年 8 月


   当 PSK 在带外提供时,还 MUST 提供 PSK identity 以及将与该
   PSK 一起使用的 KDF 哈希算法。

   注意:使用带外提供的预共享秘密时,一个关键考虑是密钥生成期间
      使用足够的熵,如 [RFC4086] 中所讨论。从密码或其他低熵来源
      派生共享秘密是不安全的。低熵秘密或密码会受到基于 PSK
      binder 的字典攻击。即使与 Diffie-Hellman 密钥建立一起使用,
      所规定的 PSK 认证也不是强口令认证密钥交换。具体而言,它
      不能阻止能够观察握手的攻击者对密码/预共享密钥进行暴力破解
      攻击。

2.3.  0-RTT 数据

   当客户端和服务器共享 PSK(无论是外部获得还是通过此前握手
   获得)时,TLS 1.3 允许客户端在第一趟发送数据(“early data”)。
   客户端使用 PSK 来认证服务器并加密 early data。

   如图 4 所示,0-RTT 数据只是在第一趟中添加到 1-RTT 握手。
   其余握手使用与带 PSK 恢复的 1-RTT 握手相同的消息。



























Rescorla                     标准化进程                      [第 17 页]


RFC 8446                           TLS                       2018 年 8 月


         客户端                                               服务器

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

               +  表示在前面标注的消息中发送的值得注意的扩展。

               *  表示并非总是发送的可选或取决于情形的
                  消息/扩展。

               () 表示使用从 client_early_traffic_secret 派生的
                  密钥保护的消息。

               {} 表示使用从 [sender]_handshake_traffic_secret
                  派生的密钥保护的消息。

               [] 表示使用从 [sender]_application_traffic_secret_N
                  派生的密钥保护的消息。

               图 4:0-RTT 握手的消息流
















Rescorla                     标准化进程                      [第 18 页]


RFC 8446                           TLS                       2018 年 8 月


   重要说明:0-RTT 数据的安全属性弱于其他类型的 TLS 数据。具体
   而言:

   1.  此数据不具备前向保密,因为它仅使用基于所提供 PSK 派生的
       密钥进行加密。

   2.  不保证连接之间不可重放。普通 TLS 1.3 1-RTT 数据的重放
       保护由服务器的 Random 值提供,但 0-RTT 数据不依赖
       ServerHello,因此保证较弱。如果数据是通过 TLS 客户端认证
       或在应用协议内部进行认证,这一点尤其相关。同样的警告也
       适用于 early_exporter_master_secret 的任何使用。

   0-RTT 数据不能在连接内被复制(即服务器不会为同一连接处理同一
   数据两次),攻击者也不能让 0-RTT 数据看起来像 1-RTT 数据
   (因为它使用不同的密钥保护)。附录 E.5包含潜在攻击的描述,
   第 8 节描述了服务器可用于限制重放影响的机制。

3.  表示语言

   本文档处理外部表示中数据的格式。下面将使用一种非常基础且
   略微非正式定义的表示语法。

3.1.  基本块大小

   所有数据项的表示都被显式规定。基本数据块大小为一个字节
   (即 8 位)。多字节数据项是字节的串接,顺序为从左到右、
   从上到下。从字节流中形成一个多字节项(以下示例中为数值)
   的方式(使用 C 记法)如下:

      value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
              ... | byte[n-1];

   这种多字节值的字节顺序就是常见的网络字节序或大端格式。










Rescorla                     标准化进程                      [第 19 页]


RFC 8446                           TLS                       2018 年 8 月


3.2.  其他事项

   注释以“/*”开始,并以“*/”结束。

   可选组件通过用“[[ ]]”(双括号)括起来表示。

   含有未解释数据的单字节实体属于 opaque 类型。

   现有类型 T 的类型别名 T' 按如下方式定义:

      T T';

3.3.  数字

   基本数值数据类型是无符号字节(uint8)。所有更大的数值数据
   类型都由固定长度的字节序列构造而成,按第 3.1 节所述方式
   串接,并且同样是无符号的。以下数值类型是预定义的。

      uint8 uint16[2];
      uint8 uint24[3];
      uint8 uint32[4];
      uint8 uint64[8];

   本规范中这里和其他地方的所有值,都按网络字节(大端)顺序
   传输;由十六进制字节 01 02 03 04 表示的 uint32 等同于十进制
   值 16909060。

3.4.  向量

   向量(单维数组)是同质数据元素的流。向量的大小可以在文档
   编写时指定,也可以留到运行时再指定。无论哪种情况,长度声明的
   都是向量中的字节数,而不是元素数量。用于指定新类型 T' 的语法
   如下,其中 T' 是类型 T 的固定长度向量:

      T T'[n];

   此处,T' 在数据流中占用 n 个字节,其中 n 是 T 大小的倍数。
   向量的长度不包含在编码流中。







Rescorla                     标准化进程                      [第 20 页]


RFC 8446                           TLS                       2018 年 8 月


   在以下示例中,Datum 被定义为协议不解释的三个连续字节,而
   Data 是三个连续的 Datum,总共占用九个字节。

      opaque Datum[3];      /* three uninterpreted bytes */
      Datum Data[9];        /* three consecutive 3-byte vectors */

   变长向量通过用记法 <floor..ceiling> 指定合法长度子范围(包含
   两端)来定义。当这些向量被编码时,实际长度位于向量内容之前的
   字节流中。长度将以一个数字的形式出现,该数字占用的字节数足以
   容纳向量指定的最大(ceiling)长度。实际长度字段为零的变长
   向量称为空向量。

      T T'<floor..ceiling>;

   在以下示例中,“mandatory”是一个必须包含 300 到 400 个 opaque
   类型字节的向量。它永远不能为空。实际长度字段占用两个字节,即
   uint16,足以表示值 400(见第 3.3 节)。类似地,“longer”
   最多可以表示 800 字节数据,或 400 个 uint16 元素,并且可以
   为空。其编码会包含一个置于向量之前的两字节实际长度字段。
   编码向量的长度必须是单个元素长度的精确倍数(例如,17 字节的
   uint16 向量将是非法的)。

      opaque mandatory<300..400>;
            /* length field is two bytes, cannot be empty */
      uint16 longer<0..800>;
            /* zero to 400 16-bit unsigned integers */

3.5.  枚举

   还有一种额外的稀疏数据类型,称为“enum”或“enumerated”。
   每个定义都是不同的类型。只有同一类型的枚举才能被赋值或比较。
   枚举中的每个元素都必须被赋予一个值,如以下示例所示。由于枚举
   元素没有顺序,它们可以按任意顺序赋予任何唯一值。

      enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;

   协议的未来扩展或添加可能定义新的值。除非字段定义另有说明,
   实现需要能够解析并忽略未知值。





Rescorla                     标准化进程                      [第 21 页]


RFC 8446                           TLS                       2018 年 8 月


   枚举在字节流中占用的空间与其最大定义序数值所需空间相同。
   以下定义会使 Color 类型字段使用一个字节来承载。

      enum { red(3), blue(5), white(7) } Color;

   可以选择性地指定一个不带关联标签的值,以在不定义多余元素的
   情况下强制宽度定义。

   在以下示例中,Taste 将在数据流中占用两个字节,但在当前协议
   版本中只能取值 1、2 或 4。

      enum { sweet(1), sour(2), bitter(4), (32000) } Taste;

   枚举元素的名称限定在所定义类型的作用域内。在第一个示例中,
   对枚举第二个元素的完全限定引用将是 Color.blue。如果赋值目标
   已经明确指定,则不需要这种限定。

      Color color = Color.blue;     /* overspecified, legal */
      Color color = blue;           /* correct, type implicit */

   分配给枚举的名称不需要唯一。数值可以描述同一名称适用的范围。
   该值包含该范围中最小和最大两个包含端点值,中间由两个句点字符
   分隔。这主要用于保留空间中的区域。

      enum { sad(0), meh(1..254), happy(255) } Mood;

3.6.  构造类型

   为方便起见,可以从原始类型构造结构类型。每个规范声明一个新的
   唯一类型。用于定义的语法非常类似于 C。

      struct {
          T1 f1;
          T2 f2;
          ...
          Tn fn;
      } T;

   可以使用标准向量语法来允许固定长度和变长向量字段。变体示例
   (第 3.8 节)中的结构 V1 和 V2 演示了这一点。



Rescorla                     标准化进程                      [第 22 页]


RFC 8446                           TLS                       2018 年 8 月


   结构中的字段可以使用类型名称限定,其语法非常类似于枚举可用的
   语法。例如,T.f2 指前一个声明中的第二个字段。

3.7.  常量

   字段和变量可以使用“=”赋予固定值,如:

      struct {
          T1 f1 = 8;  /* T.f1 must always be 8 */
          T2 f2;
      } T;

3.8.  变体

   已定义的结构可以根据环境中可用的某些知识具有变体。选择器必须
   是一种枚举类型,定义该结构可具有的可能变体。select 的每个分支
   (如下)都指定该变体字段的类型以及可选字段标签。表示语言不
   规定运行时选择变体的机制。

      struct {
          T1 f1;
          T2 f2;
          ....
          Tn fn;
          select (E) {
              case e1: Te1 [[fe1]];
              case e2: Te2 [[fe2]];
              ....
              case en: Ten [[fen]];
          };
      } Tv;

















Rescorla                     标准化进程                      [第 23 页]


RFC 8446                           TLS                       2018 年 8 月


   例如:

      enum { apple(0), orange(1) } VariantTag;

      struct {
          uint16 number;
          opaque string<0..10>; /* variable length */
      } V1;

      struct {
          uint32 number;
          opaque string[10];    /* fixed length */
      } V2;

      struct {
          VariantTag type;
          select (VariantRecord.type) {
              case apple:  V1;
              case orange: V2;
          };
      } VariantRecord;

4.  握手协议

   握手协议用于协商连接的安全参数。握手消息被提供给 TLS 记录层,
   在那里它们被封装到一个或多个 TLSPlaintext 或 TLSCiphertext
   结构中,并根据当前活动连接状态的规定进行处理和传输。






















Rescorla                     标准化进程                      [第 24 页]


RFC 8446                           TLS                       2018 年 8 月


      enum {
          client_hello(1),
          server_hello(2),
          new_session_ticket(4),
          end_of_early_data(5),
          encrypted_extensions(8),
          certificate(11),
          certificate_request(13),
          certificate_verify(15),
          finished(20),
          key_update(24),
          message_hash(254),
          (255)
      } HandshakeType;

      struct {
          HandshakeType msg_type;    /* handshake type */
          uint24 length;             /* remaining bytes in message */
          select (Handshake.msg_type) {
              case client_hello:          ClientHello;
              case server_hello:          ServerHello;
              case end_of_early_data:     EndOfEarlyData;
              case encrypted_extensions:  EncryptedExtensions;
              case certificate_request:   CertificateRequest;
              case certificate:           Certificate;
              case certificate_verify:    CertificateVerify;
              case finished:              Finished;
              case new_session_ticket:    NewSessionTicket;
              case key_update:            KeyUpdate;
          };
      } Handshake;

   协议消息 MUST 按第 4.4.1 节定义并在第 2 节图示中显示的顺序
   发送。收到意外顺序握手消息的对等方 MUST 使用
   “unexpected_message”告警中止握手。

   新的握手消息类型由 IANA 按第 11 节所述分配。

4.1.  密钥交换消息

   密钥交换消息用于确定客户端和服务器的安全能力,并建立共享秘密,
   包括用于保护其余握手和数据的流量密钥。





Rescorla                     标准化进程                      [第 25 页]


RFC 8446                           TLS                       2018 年 8 月


4.1.1.  密码协商

   在 TLS 中,密码协商通过客户端在其 ClientHello 中提供以下四组
   选项来进行:

   -  一个密码套件列表,指明客户端支持的 AEAD 算法/HKDF 哈希对。

   -  一个“supported_groups”(第 4.2.7 节)扩展,指明客户端支持的
      (EC)DHE 组;以及一个“key_share”(第 4.2.8 节)扩展,
      包含这些组中部分或全部组的 (EC)DHE 份额。

   -  一个“signature_algorithms”(第 4.2.3 节)扩展,指明客户端
      可以接受的签名算法。还可以添加“signature_algorithms_cert”
      扩展(第 4.2.3 节)以指明证书特定的签名算法。

   -  一个“pre_shared_key”(第 4.2.11 节)扩展,其中包含客户端已知的
      对称密钥 identity 列表;以及一个“psk_key_exchange_modes”
      (第 4.2.9 节)扩展,指明可与 PSK 一起使用的密钥交换模式。

   如果服务器未选择 PSK,则这些选项中的前三项完全正交:服务器
   独立选择密码套件、用于密钥建立的 (EC)DHE 组和密钥份额,以及
   用于向客户端认证自身的签名算法/证书对。如果收到的
   “supported_groups”和服务器支持的组之间没有交集,则服务器
   MUST 使用“handshake_failure”或“insufficient_security”告警中止
   握手。

   如果服务器选择 PSK,则它还 MUST 从客户端“psk_key_exchange_modes”
   扩展所指示的集合中选择一个密钥建立模式(目前为仅 PSK 或带
   (EC)DHE)。注意,如果 PSK 可以不与 (EC)DHE 一起使用,那么
   “supported_groups”参数没有交集不必是致命的,这不同于前一段
   所讨论的非 PSK 情况。

   如果服务器选择 (EC)DHE 组,而客户端没有在初始 ClientHello 中
   提供兼容的“key_share”扩展,则服务器 MUST 以 HelloRetryRequest
   (第 4.1.4 节)消息响应。









Rescorla                     标准化进程                      [第 26 页]


RFC 8446                           TLS                       2018 年 8 月


   如果服务器成功选择参数且不需要 HelloRetryRequest,它会在
   ServerHello 中按如下方式指明所选参数:

   -  如果正在使用 PSK,则服务器将发送“pre_shared_key”扩展,
      指明所选密钥。

   -  当使用 (EC)DHE 时,服务器还将提供“key_share”扩展。如果
      未使用 PSK,则始终使用 (EC)DHE 和基于证书的认证。

   -  当通过证书进行认证时,服务器将发送 Certificate
      (第 4.4.2 节)和 CertificateVerify(第 4.4.3 节)消息。
      在本文档定义的 TLS 1.3 中,始终使用 PSK 或证书之一,但
      不能两者同时使用。未来文档可能定义如何将它们一起使用。

   如果服务器无法协商出一组受支持的参数(即客户端和服务器参数
   之间没有交集),它 MUST 使用“handshake_failure”或
   “insufficient_security”致命告警中止握手(见第 6 节)。

4.1.2.  Client Hello

   当客户端首次连接到服务器时,REQUIRED 将 ClientHello 作为其
   第一条 TLS 消息发送。当服务器以 HelloRetryRequest 响应其
   ClientHello 时,客户端也将发送 ClientHello。在这种情况下,
   客户端 MUST 发送同一个 ClientHello,除以下内容外不得修改:

   -  如果 HelloRetryRequest 中提供了“key_share”扩展,则将
      份额列表替换为包含来自所指示组的单个 KeyShareEntry 的
      列表。

   -  如果存在“early_data”扩展(第 4.2.10 节),则移除它。
      HelloRetryRequest 之后不允许 early data。

   -  如果 HelloRetryRequest 中提供了“cookie”扩展,则包含该扩展。












Rescorla                     标准化进程                      [第 27 页]


RFC 8446                           TLS                       2018 年 8 月


   -  如果存在“pre_shared_key”扩展,则通过重新计算
      “obfuscated_ticket_age”和 binder 值,并(可选地)移除与服务器
      指示的密码套件不兼容的任何 PSK,来更新该扩展。

   -  可选地添加、移除或更改“padding”扩展 [RFC7685] 的长度。

   -  未来定义并出现在 HelloRetryRequest 中的扩展可能允许的其他
      修改。

   由于 TLS 1.3 禁止重新协商,如果服务器已经协商了 TLS 1.3,
   并在任何其他时间收到 ClientHello,它 MUST 使用
   “unexpected_message”告警终止连接。

   如果服务器使用先前版本的 TLS 建立了 TLS 连接,并在重新协商中
   收到 TLS 1.3 ClientHello,它 MUST 保留先前的协议版本。特别是,
   它 MUST NOT 协商 TLS 1.3。

   此消息的结构:

      uint16 ProtocolVersion;
      opaque Random[32];

      uint8 CipherSuite[2];    /* Cryptographic suite selector */

      struct {
          ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
          Random random;
          opaque legacy_session_id<0..32>;
          CipherSuite cipher_suites<2..2^16-2>;
          opaque legacy_compression_methods<1..2^8-1>;
          Extension extensions<8..2^16-1>;
      } ClientHello;
















Rescorla                     标准化进程                      [第 28 页]


RFC 8446                           TLS                       2018 年 8 月


   legacy_version:在 TLS 的先前版本中,此字段用于版本协商,并
      表示客户端支持的最高版本号。经验表明,许多服务器并没有
      正确实现版本协商,导致“版本不耐受”,即服务器会拒绝一个
      版本号高于其所支持版本、但本来可接受的 ClientHello。在
      TLS 1.3 中,客户端在“supported_versions”扩展
      (第 4.2.1 节)中指明其版本偏好,而 legacy_version 字段
      MUST 设置为 0x0303,这是 TLS 1.2 的版本号。TLS 1.3
      ClientHello 被识别为 legacy_version 为 0x0303,并且存在
      supported_versions 扩展,其中指示的最高版本为 0x0304。
      (关于向后兼容性的细节,见附录 D。)

   random:由安全随机数生成器生成的 32 字节。更多信息见
      附录 C。

   legacy_session_id:TLS 1.3 之前的 TLS 版本支持“session
      resumption”特性,该特性在本版本中已与预共享密钥合并
      (见第 2.2 节)。缓存了由 TLS 1.3 之前服务器设置的会话 ID
      的客户端 SHOULD 将此字段设置为该值。在兼容模式下
      (见附录 D.4),此字段 MUST 非空,因此未提供 TLS 1.3 之前
      会话的客户端 MUST 生成新的 32 字节值。此值不必是随机的,
      但 SHOULD 是不可预测的,以避免实现固定在某个特定值上
      (也称为僵化)。否则,它 MUST 设置为零长度向量(即一个
      值为零的单字节长度字段)。

   cipher_suites:客户端支持的对称密码选项列表,具体为记录保护
      算法(包括秘密密钥长度)以及与 HKDF 一起使用的哈希,按
      客户端偏好降序排列。值在附录 B.4中定义。如果列表包含
      服务器不识别、不支持或不希望使用的密码套件,服务器 MUST
      忽略这些密码套件,并照常处理其余密码套件。如果客户端正在
      尝试 PSK 密钥建立,它 SHOULD 至少通告一个指示与该 PSK
      关联的 Hash 的密码套件。












Rescorla                     标准化进程                      [第 29 页]


RFC 8446                           TLS                       2018 年 8 月


   legacy_compression_methods:TLS 1.3 之前的 TLS 版本支持压缩,
      并在此字段中发送受支持的压缩方法列表。对于每个 TLS 1.3
      ClientHello,此向量 MUST 只包含一个字节,且设为零,该值对应
      于 TLS 先前版本中的“null”压缩方法。如果收到的 TLS 1.3
      ClientHello 在此字段中带有任何其他值,服务器 MUST 使用
      “illegal_parameter”告警中止握手。注意,TLS 1.3 服务器可能会
      收到包含其他压缩方法的 TLS 1.2 或更早版本 ClientHello,并且
      (如果协商此类先前版本)MUST 遵循相应先前 TLS 版本的流程。

   extensions:客户端通过在 extensions 字段中发送数据来向服务器
      请求扩展功能。实际的“Extension”格式在第 4.2 节中定义。
      在 TLS 1.3 中,某些扩展的使用是强制性的,因为功能已移入
      扩展,以保持 ClientHello 与 TLS 先前版本的兼容性。服务器
      MUST 忽略未识别的扩展。

   所有 TLS 版本都允许 extensions 字段可选地跟在
   compression_methods 字段之后。TLS 1.3 ClientHello 消息始终
   包含扩展(至少包含“supported_versions”,否则它们会被解释为
   TLS 1.2 ClientHello 消息)。然而,TLS 1.3 服务器可能会从 TLS
   先前版本接收到不带 extensions 字段的 ClientHello 消息。扩展的
   存在可以通过判断 ClientHello 末尾 compression_methods 字段之后
   是否还有字节来检测。注意,这种检测可选数据的方法不同于通常的
   TLS 变长字段方法,但它用于与扩展定义之前的 TLS 兼容。TLS 1.3
   服务器需要首先执行此检查,并且只有在存在“supported_versions”
   扩展时才尝试协商 TLS 1.3。如果协商 TLS 1.3 之前的版本,服务器
   MUST 检查消息要么在 legacy_compression_methods 之后不包含数据,
   要么包含一个有效的扩展块且其后没有数据。否则,它 MUST 使用
   “decode_error”告警中止握手。

   如果客户端使用扩展请求额外功能,而服务器未提供该功能,客户端
   MAY 中止握手。

   发送 ClientHello 消息后,客户端等待 ServerHello 或
   HelloRetryRequest 消息。如果正在使用 early data,客户端可以在
   等待下一条握手消息时传输 early Application Data(第 2.3 节)。





Rescorla                     标准化进程                      [第 30 页]


RFC 8446                           TLS                       2018 年 8 月


4.1.3.  Server Hello

   如果服务器能够根据 ClientHello 协商出可接受的一组握手参数以
   继续握手,它将响应 ClientHello 消息发送此消息。

   此消息的结构:

      struct {
          ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
          Random random;
          opaque legacy_session_id_echo<0..32>;
          CipherSuite cipher_suite;
          uint8 legacy_compression_method = 0;
          Extension extensions<6..2^16-1>;
      } ServerHello;

   legacy_version:在 TLS 的先前版本中,此字段用于版本协商,并
      表示为连接选择的版本号。不幸的是,一些中间盒在遇到新值时会
      失败。在 TLS 1.3 中,TLS 服务器使用“supported_versions”扩展
      (第 4.2.1 节)指明其版本,legacy_version 字段 MUST 设置为
      0x0303,这是 TLS 1.2 的版本号。(关于向后兼容性的细节,见
      附录 D。)

   random:由安全随机数生成器生成的 32 字节。更多信息见
      附录 C。如果协商 TLS 1.2 或 TLS 1.1,最后 8 字节 MUST 按
      下文所述被覆盖,但其余字节 MUST 是随机的。该结构由服务器
      生成,并且 MUST 独立于 ClientHello.random 生成。

   legacy_session_id_echo:客户端 legacy_session_id 字段的内容。
      注意,即使客户端的值对应于一个已缓存的 TLS 1.3 之前会话,
      且服务器选择不恢复该会话,此字段也会被回显。客户端如果收到
      与其在 ClientHello 中发送内容不匹配的 legacy_session_id_echo
      字段,MUST 使用“illegal_parameter”告警中止握手。

   cipher_suite:服务器从 ClientHello.cipher_suites 列表中选择的
      单个密码套件。客户端如果收到未被提供过的密码套件,MUST 使用
      “illegal_parameter”告警中止握手。

   legacy_compression_method:单个字节,MUST 具有值 0。



Rescorla                     标准化进程                      [第 31 页]


RFC 8446                           TLS                       2018 年 8 月


   extensions:扩展列表。ServerHello MUST 只包含建立密码上下文和
      协商协议版本所需的扩展。所有 TLS 1.3 ServerHello 消息 MUST
      包含“supported_versions”扩展。当前的 ServerHello 消息还包含
      “pre_shared_key”扩展或“key_share”扩展,或两者都包含(当使用
      带 (EC)DHE 密钥建立的 PSK 时)。其他扩展(见第 4.2 节)
      在 EncryptedExtensions 消息中单独发送。

   出于与中间盒向后兼容的原因(见附录 D.4),HelloRetryRequest
   消息使用与 ServerHello 相同的结构,但 Random 被设置为
   “HelloRetryRequest”的 SHA-256 特殊值:

     CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
     C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C

   收到类型为 server_hello 的消息时,实现 MUST 首先检查 Random
   值,如果它匹配此值,则按照第 4.1.4 节所述处理)。

   TLS 1.3 在服务器的 random 值中嵌入了降级保护机制。TLS 1.3
   服务器如果响应 ClientHello 协商 TLS 1.2 或以下版本,MUST 在其
   ServerHello 中对 Random 值的最后 8 字节进行特殊设置。

   如果协商 TLS 1.2,TLS 1.3 服务器 MUST 将其 Random 值的最后
   8 字节设置为以下字节:

     44 4F 57 4E 47 52 44 01

   如果协商 TLS 1.1 或以下版本,TLS 1.3 服务器 MUST、TLS 1.2
   服务器 SHOULD 将其 ServerHello.Random 值的最后 8 字节设置为
   以下字节:

     44 4F 57 4E 47 52 44 00

   TLS 1.3 客户端在收到指示 TLS 1.2 或以下版本的 ServerHello 时,
   MUST 检查最后 8 字节不等于这两个值中的任一值。如果 ServerHello
   指示 TLS 1.1 或以下版本,TLS 1.2 客户端 SHOULD 也检查最后
   8 字节不等于第二个值。如果发现匹配,客户端 MUST 使用
   “illegal_parameter”告警中止握手。该机制提供的降级攻击保护
   超出了 Finished 交换所提供的保护,但保护是有限的:因为
   ServerKeyExchange(存在于 TLS 1.2 及以下版本中的一条消息)
   包含对两个 random 值的签名,只要使用临时密码,主动攻击者就
   不可能在不被检测到的情况下修改这些 random 值。它在使用静态
   RSA 时不提供降级保护。



Rescorla                     标准化进程                      [第 32 页]


RFC 8446                           TLS                       2018 年 8 月


   注意:这是相对于 [RFC5246] 的一项更改,因此在实践中许多 TLS
   1.2 客户端和服务器不会按上文规定行事。

   使用 TLS 1.2 或更早版本执行重新协商的遗留 TLS 客户端,如果在
   重新协商期间收到 TLS 1.3 ServerHello,MUST 使用
   “protocol_version”告警中止握手。注意,当已协商 TLS 1.3 时,
   不可能进行重新协商。

4.1.4.  Hello Retry Request

   如果服务器能够找到一组可接受的参数,但 ClientHello 未包含足以
   继续握手的信息,服务器将响应 ClientHello 消息发送此消息。如
   第 4.1.3 节所述,HelloRetryRequest 与 ServerHello 消息具有相同
   格式,并且 legacy_version、legacy_session_id_echo、cipher_suite
   和 legacy_compression_method 字段具有相同含义。然而,为方便起见,
   本文档仍像它是不同消息一样讨论“HelloRetryRequest”。

   服务器的扩展 MUST 包含“supported_versions”。此外,它 SHOULD
   包含客户端生成正确 ClientHello 对所需的最小扩展集合。与
   ServerHello 一样,HelloRetryRequest MUST NOT 包含客户端未先在
   其 ClientHello 中提供的任何扩展,但可选的“cookie”(见
   第 4.2.2 节)扩展除外。

   收到 HelloRetryRequest 后,客户端 MUST 按第 4.1.3 节规定检查
   legacy_version、legacy_session_id_echo、cipher_suite 和
   legacy_compression_method,然后处理扩展,首先使用
   “supported_versions”确定版本。如果 HelloRetryRequest 不会导致
   ClientHello 发生任何变化,客户端 MUST 使用“illegal_parameter”
   告警中止握手。如果客户端在同一连接中收到第二个
   HelloRetryRequest(即 ClientHello 本身就是对 HelloRetryRequest
   的响应),它 MUST 使用“unexpected_message”告警中止握手。









Rescorla                     标准化进程                      [第 33 页]


RFC 8446                           TLS                       2018 年 8 月


   否则,客户端 MUST 处理 HelloRetryRequest 中的所有扩展,并发送
   第二个更新后的 ClientHello。本规范定义的 HelloRetryRequest 扩展为:

   -  supported_versions(见第 4.2.1 节)

   -  cookie(见第 4.2.2 节)

   -  key_share(见第 4.2.8 节)

   收到未提供过的密码套件的客户端 MUST 中止握手。服务器 MUST
   确保在收到符合规范的更新后 ClientHello 时协商相同的密码套件
   (如果服务器将选择密码套件作为协商的第一步,则这会自动发生)。
   收到 ServerHello 后,客户端 MUST 检查 ServerHello 中提供的密码
   套件与 HelloRetryRequest 中的相同,否则使用“illegal_parameter”
   告警中止握手。

   此外,在更新后的 ClientHello 中,客户端 SHOULD NOT 提供任何与
   所选密码套件的哈希不同的哈希相关联的预共享密钥。这使客户端可
   避免必须为第二个 ClientHello 计算多个哈希的部分哈希 transcript。

   HelloRetryRequest“supported_versions”扩展中的 selected_version
   值 MUST 保留在 ServerHello 中;如果该值发生变化,客户端 MUST
   使用“illegal_parameter”告警中止握手。






















Rescorla                     标准化进程                      [第 34 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.  扩展

   许多 TLS 消息包含以 tag-length-value 编码的扩展结构。

    struct {
        ExtensionType extension_type;
        opaque extension_data<0..2^16-1>;
    } Extension;

    enum {
        server_name(0),                             /* RFC 6066 */
        max_fragment_length(1),                     /* RFC 6066 */
        status_request(5),                          /* RFC 6066 */
        supported_groups(10),                       /* RFC 8422, 7919 */
        signature_algorithms(13),                   /* RFC 8446 */
        use_srtp(14),                               /* RFC 5764 */
        heartbeat(15),                              /* RFC 6520 */
        application_layer_protocol_negotiation(16), /* RFC 7301 */
        signed_certificate_timestamp(18),           /* RFC 6962 */
        client_certificate_type(19),                /* RFC 7250 */
        server_certificate_type(20),                /* RFC 7250 */
        padding(21),                                /* RFC 7685 */
        pre_shared_key(41),                         /* RFC 8446 */
        early_data(42),                             /* RFC 8446 */
        supported_versions(43),                     /* RFC 8446 */
        cookie(44),                                 /* RFC 8446 */
        psk_key_exchange_modes(45),                 /* RFC 8446 */
        certificate_authorities(47),                /* RFC 8446 */
        oid_filters(48),                            /* RFC 8446 */
        post_handshake_auth(49),                    /* RFC 8446 */
        signature_algorithms_cert(50),              /* RFC 8446 */
        key_share(51),                              /* RFC 8446 */
        (65535)
    } ExtensionType;
















Rescorla                     标准化进程                      [第 35 页]


RFC 8446                           TLS                       2018 年 8 月


   这里:

   -  “extension_type”标识具体的扩展类型。

   -  “extension_data”包含特定于具体扩展类型的信息。

   扩展类型列表由 IANA 维护,如第 11 节所述。

   扩展通常以请求/响应方式构造,不过有些扩展只是没有相应响应的
   指示。客户端在 ClientHello 消息中发送其扩展请求,服务器在
   ServerHello、EncryptedExtensions、HelloRetryRequest 和 Certificate
   消息中发送其扩展响应。服务器在 CertificateRequest 消息中发送
   扩展请求,客户端 MAY 用 Certificate 消息响应。服务器也 MAY 在
   NewSessionTicket 中发送未经请求的扩展,不过客户端不会直接响应
   这些扩展。

   除 HelloRetryRequest 中的“cookie”扩展外,如果远程端点没有发送
   相应的扩展请求,实现 MUST NOT 发送扩展响应。端点收到此类扩展时,
   MUST 使用“unsupported_extension”告警中止握手。

   下表指明给定扩展可以出现在哪些消息中,使用以下记法:
   CH(ClientHello)、SH(ServerHello)、EE(EncryptedExtensions)、
   CT(Certificate)、CR(CertificateRequest)、NST(NewSessionTicket)
   和 HRR(HelloRetryRequest)。如果实现收到其识别的扩展,而该
   扩展未被指定用于它所在的消息中,则它 MUST 使用
   “illegal_parameter”告警中止握手。
















Rescorla                     标准化进程                      [第 36 页]


RFC 8446                           TLS                       2018 年 8 月


   +--------------------------------------------------+-------------+
   | 扩展                                             |     TLS 1.3 |
   +--------------------------------------------------+-------------+
   | server_name [RFC6066]                            |      CH, EE |
   |                                                  |             |
   | max_fragment_length [RFC6066]                    |      CH, EE |
   |                                                  |             |
   | status_request [RFC6066]                         |  CH, CR, CT |
   |                                                  |             |
   | supported_groups [RFC7919]                       |      CH, EE |
   |                                                  |             |
   | signature_algorithms (RFC 8446)                  |      CH, CR |
   |                                                  |             |
   | use_srtp [RFC5764]                               |      CH, EE |
   |                                                  |             |
   | heartbeat [RFC6520]                              |      CH, EE |
   |                                                  |             |
   | application_layer_protocol_negotiation [RFC7301] |      CH, EE |
   |                                                  |             |
   | signed_certificate_timestamp [RFC6962]           |  CH, CR, CT |
   |                                                  |             |
   | client_certificate_type [RFC7250]                |      CH, EE |
   |                                                  |             |
   | server_certificate_type [RFC7250]                |      CH, EE |
   |                                                  |             |
   | padding [RFC7685]                                |          CH |
   |                                                  |             |
   | key_share (RFC 8446)                             | CH, SH, HRR |
   |                                                  |             |
   | pre_shared_key (RFC 8446)                        |      CH, SH |
   |                                                  |             |
   | psk_key_exchange_modes (RFC 8446)                |          CH |
   |                                                  |             |
   | early_data (RFC 8446)                            | CH, EE, NST |
   |                                                  |             |
   | cookie (RFC 8446)                                |     CH, HRR |
   |                                                  |             |
   | supported_versions (RFC 8446)                    | CH, SH, HRR |
   |                                                  |             |
   | certificate_authorities (RFC 8446)               |      CH, CR |
   |                                                  |             |
   | oid_filters (RFC 8446)                           |          CR |
   |                                                  |             |
   | post_handshake_auth (RFC 8446)                   |          CH |
   |                                                  |             |
   | signature_algorithms_cert (RFC 8446)             |      CH, CR |
   +--------------------------------------------------+-------------+




Rescorla                     标准化进程                      [第 37 页]


RFC 8446                           TLS                       2018 年 8 月


   当存在多个不同类型的扩展时,扩展 MAY 以任意顺序出现,但
   “pre_shared_key”(第 4.2.11 节)例外,它 MUST 是 ClientHello
   中的最后一个扩展(但可以出现在 ServerHello 扩展块中的任何
   位置)。在给定的扩展块中 MUST NOT 存在多个同一类型的扩展。

   在 TLS 1.3 中,不同于 TLS 1.2,即使处于恢复-PSK 模式,扩展也会
   为每次握手进行协商。然而,0-RTT 参数是前一次握手中协商的参数;
   不匹配可能要求拒绝 0-RTT(见第 4.2.10 节)。

   在此协议中,新特性与现有特性之间可能发生微妙(以及不那么微妙)
   的交互,从而可能导致整体安全性显著降低。设计新扩展时应考虑
   以下事项:

   -  某些服务器不同意某个扩展的情况属于错误条件(例如,握手无法
      继续),而有些只是拒绝支持特定特性。一般来说,前者应使用
      错误告警,后者应使用服务器扩展响应中的字段。

   -  扩展在设计时应尽可能防止任何通过操纵握手消息来强制使用
      (或不使用)某个特性的攻击。无论该特性是否被认为会造成安全
      问题,都应遵循此原则。通常,将扩展字段包含在 Finished 消息
      哈希的输入中就足够了,但当扩展改变握手阶段发送消息的含义时,
      需要极其谨慎。设计者和实现者应意识到,在握手被认证之前,
      主动攻击者可以修改消息,并插入、移除或替换扩展。
















Rescorla                     标准化进程                      [第 38 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.1.  Supported Versions

      struct {
          select (Handshake.msg_type) {
              case client_hello:
                   ProtocolVersion versions<2..254>;

              case server_hello: /* and HelloRetryRequest */
                   ProtocolVersion selected_version;
          };
      } SupportedVersions;

   “supported_versions”扩展由客户端用于指明其支持哪些 TLS 版本,
   由服务器用于指明其正在使用哪个版本。该扩展包含按偏好顺序排列
   的受支持版本列表,最偏好的版本在前。本规范的实现 MUST 在
   ClientHello 中发送此扩展,包含它们准备协商的所有 TLS 版本
   (对于本规范,这意味着至少包含 0x0304,但如果允许协商 TLS
   先前版本,则这些版本也 MUST 出现)。

   如果不存在此扩展,符合本规范并且也支持 TLS 1.2 的服务器 MUST
   按 [RFC5246] 中的规定协商 TLS 1.2 或更早版本,即使
   ClientHello.legacy_version 为 0x0304 或更高。服务器 MAY 在收到
   legacy_version 为 0x0304 或更高的 ClientHello 时中止握手。

   如果此扩展存在于 ClientHello 中,服务器 MUST NOT 使用
   ClientHello.legacy_version 值进行版本协商,并且 MUST 只使用
   “supported_versions”扩展来确定客户端偏好。服务器 MUST 只选择该
   扩展中存在的 TLS 版本,并且 MUST 忽略该扩展中存在的任何未知
   版本。注意,如果一方支持稀疏范围,此机制使协商 TLS 1.2 之前的
   版本成为可能。选择支持 TLS 先前版本的 TLS 1.3 实现 SHOULD 支持
   TLS 1.2。服务器 MUST 准备好接收包含此扩展但版本列表中不包含
   0x0304 的 ClientHello。

   协商 TLS 1.3 之前版本的服务器 MUST 设置 ServerHello.version,
   且 MUST NOT 发送“supported_versions”扩展。协商 TLS 1.3 的
   服务器 MUST 通过发送包含所选版本值(0x0304)的
   “supported_versions”扩展来响应。它 MUST 将 ServerHello.legacy_version
   字段设置为 0x0303(TLS 1.2)。客户端 MUST 在处理 ServerHello
   其余部分之前检查此扩展(虽然它们必须解析 ServerHello 才能读取
   该扩展)。如果存在此扩展,客户端 MUST 忽略
   ServerHello.legacy_version 值,并且 MUST 只使用



Rescorla                     标准化进程                      [第 39 页]


RFC 8446                           TLS                       2018 年 8 月


   “supported_versions”扩展来确定所选版本。如果 ServerHello 中的
   “supported_versions”扩展包含客户端未提供的版本,或包含 TLS 1.3
   之前的版本,客户端 MUST 使用“illegal_parameter”告警中止握手。

4.2.2.  Cookie

      struct {
          opaque cookie<1..2^16-1>;
      } Cookie;

   Cookie 有两个主要用途:

   -  允许服务器强制客户端证明其在表面网络地址上的可达性
      (从而提供一定程度的 DoS 防护)。这主要对非面向连接的传输
      有用(示例见 [RFC6347])。

   -  允许服务器将状态卸载到客户端,从而能够在不存储任何状态的
      情况下发送 HelloRetryRequest。服务器可以通过在
      HelloRetryRequest cookie 中存储 ClientHello 的哈希(用某种
      适当的完整性保护算法保护)来做到这一点。

   发送 HelloRetryRequest 时,服务器 MAY 向客户端提供“cookie”扩展
   (这是通常规则的例外;通常只能发送出现在 ClientHello 中的
   扩展)。发送新的 ClientHello 时,客户端 MUST 将 HelloRetryRequest
   中收到的扩展内容复制到新 ClientHello 的“cookie”扩展中。客户端
   MUST NOT 在后续连接的初始 ClientHello 中使用 cookie。

   当服务器以无状态方式运行时,它可能会在第一个和第二个
   ClientHello 之间收到一条未受保护的 change_cipher_spec 类型记录
   (见第 5 节)。由于服务器没有存储任何状态,这看起来就好像
   它是收到的第一条消息。以无状态方式运行的服务器 MUST 忽略这些
   记录。









Rescorla                     标准化进程                      [第 40 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.3.  签名算法

   TLS 1.3 提供两个扩展,用于指明哪些签名算法可用于数字签名。
   “signature_algorithms_cert”扩展适用于证书中的签名,而最初出现
   于 TLS 1.2 中的“signature_algorithms”扩展适用于
   CertificateVerify 消息中的签名。证书中找到的密钥也 MUST 具有
   与其所配合使用的签名算法相适合的类型。这对 RSA 密钥和 PSS
   签名尤其是个问题,如下所述。如果不存在
   “signature_algorithms_cert”扩展,则“signature_algorithms”扩展
   也适用于证书中出现的签名。希望服务器通过证书认证自身的客户端
   MUST 发送“signature_algorithms”扩展。如果服务器通过证书进行
   认证,而客户端没有发送“signature_algorithms”扩展,则服务器
   MUST 使用“missing_extension”告警中止握手(见第 9.2 节)。

   添加“signature_algorithms_cert”扩展,是为了允许那些对证书和
   TLS 本身支持不同算法集合的实现清楚地表明其能力。TLS 1.2 实现
   SHOULD 也处理此扩展。在两种情况下具有相同策略的实现 MAY 省略
   “signature_algorithms_cert”扩展。


























Rescorla                     标准化进程                      [第 41 页]


RFC 8446                           TLS                       2018 年 8 月


   这些扩展的“extension_data”字段包含一个 SignatureSchemeList 值:

      enum {
          /* RSASSA-PKCS1-v1_5 algorithms */
          rsa_pkcs1_sha256(0x0401),
          rsa_pkcs1_sha384(0x0501),
          rsa_pkcs1_sha512(0x0601),

          /* ECDSA algorithms */
          ecdsa_secp256r1_sha256(0x0403),
          ecdsa_secp384r1_sha384(0x0503),
          ecdsa_secp521r1_sha512(0x0603),

          /* RSASSA-PSS algorithms with public key OID rsaEncryption */
          rsa_pss_rsae_sha256(0x0804),
          rsa_pss_rsae_sha384(0x0805),
          rsa_pss_rsae_sha512(0x0806),

          /* EdDSA algorithms */
          ed25519(0x0807),
          ed448(0x0808),

          /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
          rsa_pss_pss_sha256(0x0809),
          rsa_pss_pss_sha384(0x080a),
          rsa_pss_pss_sha512(0x080b),

          /* Legacy algorithms */
          rsa_pkcs1_sha1(0x0201),
          ecdsa_sha1(0x0203),

          /* Reserved Code Points */
          private_use(0xFE00..0xFFFF),
          (0xFFFF)
      } SignatureScheme;

      struct {
          SignatureScheme supported_signature_algorithms<2..2^16-2>;
      } SignatureSchemeList;

   注意:此枚举名为“SignatureScheme”,因为 TLS 1.2 中已经有一个
   “SignatureAlgorithm”类型,本枚举取代了它。全文中我们使用
   “signature algorithm”这一术语。







Rescorla                     标准化进程                      [第 42 页]


RFC 8446                           TLS                       2018 年 8 月


   每个 SignatureScheme 值都列出客户端愿意验证的单个签名算法。
   这些值按偏好降序排列。注意,签名算法的输入是任意长度的消息,
   而不是摘要。传统上作用于摘要的算法,应在 TLS 中定义为先用
   指定的哈希算法对输入进行哈希,然后照常继续。上面列出的码点组
   具有以下含义:

   RSASSA-PKCS1-v1_5 算法:表示使用 RSASSA-PKCS1-v1_5 [RFC8017]
      以及 [SHS] 中定义的相应哈希算法的签名算法。这些值仅指
      出现在证书中的签名(见第 4.4.2.2 节),并未定义为用于
      已签名的 TLS 握手消息,尽管为了与 TLS 1.2 向后兼容,它们
      MAY 出现在“signature_algorithms”和“signature_algorithms_cert”
      中。

   ECDSA 算法:表示使用 ECDSA [ECDSA]、ANSI X9.62 [ECDSA] 和
      FIPS 186-4 [DSS] 中定义的相应曲线,以及 [SHS] 中定义的
      相应哈希算法的签名算法。该签名表示为 DER 编码的 [X690]
      ECDSA-Sig-Value 结构。

   RSASSA-PSS RSAE 算法:表示使用 RSASSA-PSS [RFC8017] 以及掩码生成
      函数 1 的签名算法。掩码生成函数中使用的摘要和被签名的摘要
      都是 [SHS] 中定义的相应哈希算法。Salt 的长度 MUST 等于摘要
      算法输出的长度。如果公钥承载在 X.509 证书中,则它 MUST 使用
      rsaEncryption OID [RFC5280]。

   EdDSA 算法:表示使用 [RFC8032] 或其后继者中定义的 EdDSA 的签名
      算法。注意,这些对应于“PureEdDSA”算法,而不是“prehash”
      变体。

   RSASSA-PSS PSS 算法:表示使用 RSASSA-PSS [RFC8017] 以及掩码生成
      函数 1 的签名算法。掩码生成函数中使用的摘要和被签名的摘要
      都是 [SHS] 中定义的相应哈希算法。Salt 的长度 MUST 等于摘要
      算法的长度。如果公钥承载在 X.509 证书中,则它 MUST 使用
      RSASSA-PSS OID [RFC5756]。当用于证书签名时,算法参数
      MUST 进行 DER 编码。如果对应公钥的参数存在,则签名中的参数
      MUST 与公钥中的参数相同。



Rescorla                     标准化进程                      [第 43 页]


RFC 8446                           TLS                       2018 年 8 月


   遗留算法:表示正在弃用的算法,因为它们使用了具有已知弱点的
      算法,具体而言是 SHA-1;在此上下文中,SHA-1 与 (1) 使用
      RSASSA-PKCS1-v1_5 的 RSA 或 (2) ECDSA 一起使用。这些值仅指
      出现在证书中的签名(见第 4.4.2.2 节),并未定义为用于
      已签名的 TLS 握手消息,尽管为了与 TLS 1.2 向后兼容,它们
      MAY 出现在“signature_algorithms”和“signature_algorithms_cert”
      中。端点 SHOULD NOT 协商这些算法,但仅为向后兼容而允许这样
      做。提供这些值的客户端 MUST 将它们列为最低优先级(在
      SignatureSchemeList 中列在所有其他算法之后)。TLS 1.3 服务器
      MUST NOT 提供 SHA-1 签名证书,除非没有它就无法生成有效证书链
      (见第 4.4.2.2 节)。

   自签名证书或作为信任锚的证书上的签名不会被验证,因为它们开始
   一条认证路径(见 [RFC5280] 第 3.2 节)。开始认证路径的证书
   MAY 使用未在“signature_algorithms”扩展中通告为受支持的签名
   算法。

   注意,TLS 1.2 对此扩展的定义不同。愿意协商 TLS 1.2 的 TLS 1.3
   实现在协商该版本时 MUST 按照 [RFC5246] 的要求行事。特别是:

   -  TLS 1.2 ClientHello MAY 省略此扩展。

   -  在 TLS 1.2 中,该扩展包含哈希/签名对。这些对编码在两个
      八位组中,因此分配 SignatureScheme 值时已与 TLS 1.2 的编码
      对齐。一些遗留对仍未分配。自 TLS 1.3 起,这些算法已被弃用。
      任何实现 MUST NOT 提供或协商它们。特别是,MD5 [SLOTH]、
      SHA-224 和 DSA MUST NOT 使用。

   -  ECDSA 签名方案与 TLS 1.2 的 ECDSA 哈希/签名对对齐。然而,
      旧语义并不约束签名曲线。如果协商 TLS 1.2,实现 MUST 准备好
      接受使用其在“supported_groups”扩展中通告的任何曲线的签名。

   -  通告支持 RSASSA-PSS(在 TLS 1.3 中为强制)的实现,MUST 准备好
      即使协商 TLS 1.2 也接受使用该方案的签名。在 TLS 1.2 中,
      RSASSA-PSS 与 RSA 密码套件一起使用。



Rescorla                     标准化进程                      [第 44 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.4.  证书颁发机构

   “certificate_authorities”扩展用于指明端点支持的证书颁发机构
   (CA),接收端点 SHOULD 使用这些机构来指导证书选择。

   “certificate_authorities”扩展的主体由 CertificateAuthoritiesExtension
   结构组成。

      opaque DistinguishedName<1..2^16-1>;

      struct {
          DistinguishedName authorities<3..2^16-1>;
      } CertificateAuthoritiesExtension;

   authorities:可接受证书颁发机构的可分辨名称 [X501] 列表,表示为
      DER 编码 [X690] 格式。这些可分辨名称为信任锚或下级 CA 指定
      一个期望的可分辨名称;因此,此消息可用于描述已知信任锚以及
      期望的授权空间。

   客户端 MAY 在 ClientHello 消息中发送“certificate_authorities”
   扩展。服务器 MAY 在 CertificateRequest 消息中发送它。

   “trusted_ca_keys”扩展 [RFC6066] 具有类似用途但更加复杂,
   在 TLS 1.3 中不使用(尽管它可能出现在提供 TLS 先前版本的客户端
   的 ClientHello 消息中)。

4.2.5.  OID 过滤器

   “oid_filters”扩展允许服务器提供一组 OID/值对,它希望客户端
   证书与这些对匹配。如果服务器提供此扩展,则它 MUST 只在
   CertificateRequest 消息中发送。

      struct {
          opaque certificate_extension_oid<1..2^8-1>;
          opaque certificate_extension_values<0..2^16-1>;
      } OIDFilter;

      struct {
          OIDFilter filters<0..2^16-1>;
      } OIDFilterExtension;




Rescorla                     标准化进程                      [第 45 页]


RFC 8446                           TLS                       2018 年 8 月


   filters:证书扩展 OID [RFC5280] 及其允许值的列表,以 DER 编码
      [X690] 格式表示。某些证书扩展 OID 允许多个值(例如,
      Extended Key Usage)。如果服务器包含了非空 filters 列表,则
      响应中包含的客户端证书 MUST 包含客户端所识别的所有指定扩展
      OID。对于客户端识别的每个扩展 OID,所有指定值 MUST 都存在于
      客户端证书中(但该证书 MAY 也具有其他值)。然而,客户端 MUST
      忽略并跳过任何未识别的证书扩展 OID。如果客户端忽略了一些
      必需的证书扩展 OID,并提供了不满足请求的证书,则服务器 MAY
      酌情选择在没有客户端认证的情况下继续连接,或使用
      “unsupported_certificate”告警中止握手。任何给定 OID MUST NOT
      在 filters 列表中出现多于一次。

   PKIX RFC 定义了各种证书扩展 OID 及其对应值类型。根据类型不同,
   匹配的证书扩展值不一定逐位相等。预期 TLS 实现将依赖其 PKI
   库使用证书扩展 OID 执行证书选择。

   本文档为 [RFC5280] 中定义的两个标准证书扩展定义匹配规则:

   -  如果请求中断言的所有 key usage 位也都在 Key Usage 证书扩展中
      被断言,则证书中的 Key Usage 扩展与请求匹配。

   -  如果请求中存在的所有 key purpose OID 也都能在 Extended Key
      Usage 证书扩展中找到,则证书中的 Extended Key Usage 扩展与
      请求匹配。特殊的 anyExtendedKeyUsage OID MUST NOT 用于请求。

   单独的规范可以为其他证书扩展定义匹配规则。














Rescorla                     标准化进程                      [第 46 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.6.  握手后客户端认证

   “post_handshake_auth”扩展用于指明客户端愿意执行握手后认证
   (第 4.6.2 节)。服务器 MUST NOT 向未提供此扩展的客户端发送
   握手后 CertificateRequest。服务器 MUST NOT 发送此扩展。

      struct {} PostHandshakeAuth;

   “post_handshake_auth”扩展的“extension_data”字段长度为零。

4.2.7.  支持的组

   当由客户端发送时,“supported_groups”扩展指明客户端支持用于
   密钥交换的命名组,按最偏好到最不偏好的顺序排列。

   注意:在 TLS 1.3 之前的 TLS 版本中,此扩展名为
   “elliptic_curves”,且只包含椭圆曲线组。见 [RFC8422] 和
   [RFC7919]。此扩展也曾用于协商 ECDSA 曲线。签名算法现在独立
   协商(见第 4.2.3 节)。

   此扩展的“extension_data”字段包含一个“NamedGroupList”值:

      enum {

          /* Elliptic Curve Groups (ECDHE) */
          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
          x25519(0x001D), x448(0x001E),

          /* Finite Field Groups (DHE) */
          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
          ffdhe6144(0x0103), ffdhe8192(0x0104),

          /* Reserved Code Points */
          ffdhe_private_use(0x01FC..0x01FF),
          ecdhe_private_use(0xFE00..0xFEFF),
          (0xFFFF)
      } NamedGroup;

      struct {
          NamedGroup named_group_list<2..2^16-1>;
      } NamedGroupList;




Rescorla                     标准化进程                      [第 47 页]


RFC 8446                           TLS                       2018 年 8 月


   椭圆曲线组(ECDHE):表示支持相应命名曲线,该曲线定义于
      FIPS 186-4 [DSS] 或 [RFC7748] 中。值 0xFE00 到 0xFEFF
      保留用于 Private Use [RFC8126]。

   有限域组(DHE):表示支持相应有限域组,该组定义于 [RFC7919]。
      值 0x01FC 到 0x01FF 保留用于 Private Use。

   named_group_list 中的项按发送方偏好排序(最偏好选择在前)。

   自 TLS 1.3 起,服务器允许向客户端发送“supported_groups”扩展。
   客户端在握手成功完成之前 MUST NOT 根据“supported_groups”中找到的
   任何信息采取行动,但 MAY 使用从成功完成的握手中获知的信息,在
   后续连接中更改其“key_share”扩展使用的组。如果服务器有一个比
   “key_share”扩展中那些组更偏好的组,但仍愿意接受 ClientHello,
   它 SHOULD 发送“supported_groups”以更新客户端对其偏好的看法;
   此扩展 SHOULD 包含服务器支持的所有组,无论客户端当前是否支持
   这些组。

4.2.8.  密钥份额

   “key_share”扩展包含端点的密码参数。

   客户端 MAY 发送空的 client_shares 向量,以请求服务器选择组,
   代价是额外一个往返(见第 4.1.4 节)。

      struct {
          NamedGroup group;
          opaque key_exchange<1..2^16-1>;
      } KeyShareEntry;

   group:正在交换的密钥的命名组。

   key_exchange:密钥交换信息。此字段的内容由指定组及其对应定义
      决定。有限域 Diffie-Hellman [DH76] 参数在第 4.2.8.1 节中
      描述;椭圆曲线 Diffie-Hellman 参数在第 4.2.8.2 节中描述。






Rescorla                     标准化进程                      [第 48 页]


RFC 8446                           TLS                       2018 年 8 月


   在 ClientHello 消息中,此扩展的“extension_data”字段包含一个
   “KeyShareClientHello”值:

      struct {
          KeyShareEntry client_shares<0..2^16-1>;
      } KeyShareClientHello;

   client_shares:按客户端偏好降序排列的所提供 KeyShareEntry 值列表。

   如果客户端正在请求 HelloRetryRequest,则此向量 MAY 为空。每个
   KeyShareEntry 值 MUST 对应于“supported_groups”扩展中提供的一个
   组,并且 MUST 以相同顺序出现。然而,这些值 MAY 是
   “supported_groups”扩展的非连续子集,并且 MAY 省略最偏好的组。
   如果最偏好的组较新,并且不太可能在足够多地方得到支持,从而使
   为其预生成密钥份额没有效率,就可能出现这种情况。

   客户端可以提供与其所提供受支持组数量一样多的 KeyShareEntry 值,
   每个值表示一组密钥交换参数。例如,客户端可能为若干椭圆曲线或
   多个 FFDHE 组提供份额。每个 KeyShareEntry 的 key_exchange 值
   MUST 独立生成。客户端 MUST NOT 为同一组提供多个 KeyShareEntry
   值。客户端 MUST NOT 为未列在客户端“supported_groups”扩展中的组
   提供任何 KeyShareEntry 值。服务器 MAY 检查是否违反这些规则,
   并在发现违反时使用“illegal_parameter”告警中止握手。

   在 HelloRetryRequest 消息中,此扩展的“extension_data”字段包含
   一个 KeyShareHelloRetryRequest 值:

      struct {
          NamedGroup selected_group;
      } KeyShareHelloRetryRequest;

   selected_group:服务器打算协商并请求重试 ClientHello/KeyShare 的
      双方都支持的组。

   收到 HelloRetryRequest 中的此扩展时,客户端 MUST 验证:
   (1) selected_group 字段对应于原始 ClientHello 的“supported_groups”
   扩展中提供的一个组;并且 (2) selected_group 字段不对应于原始
   ClientHello 的“key_share”扩展中提供的组。如果任一检查失败,
   则客户端 MUST 使用“illegal_parameter”告警中止握手。否则,在
   发送新的 ClientHello 时,客户端 MUST



Rescorla                     标准化进程                      [第 49 页]


RFC 8446                           TLS                       2018 年 8 月


   将原始“key_share”扩展替换为一个只包含由触发的
   HelloRetryRequest 中 selected_group 字段指示的组的新
   KeyShareEntry 的扩展。

   在 ServerHello 消息中,此扩展的“extension_data”字段包含一个
   KeyShareServerHello 值:

      struct {
          KeyShareEntry server_share;
      } KeyShareServerHello;

   server_share:一个与客户端某个份额处于同一组的单个 KeyShareEntry
      值。

   如果使用 (EC)DHE 密钥建立,服务器在 ServerHello 中恰好提供一个
   KeyShareEntry。该值 MUST 与服务器为协商的密钥交换所选择的客户端
   提供的 KeyShareEntry 值处于同一组。服务器 MUST NOT 为客户端
   “supported_groups”扩展中未指明的任何组发送 KeyShareEntry,并且
   在使用“psk_ke”PskKeyExchangeMode 时 MUST NOT 发送 KeyShareEntry。
   如果使用 (EC)DHE 密钥建立,并且客户端收到包含“key_share”扩展的
   HelloRetryRequest,则客户端 MUST 验证 ServerHello 中所选
   NamedGroup 与 HelloRetryRequest 中的相同。如果此检查失败,客户端
   MUST 使用“illegal_parameter”告警中止握手。

4.2.8.1.  Diffie-Hellman 参数

   客户端和服务器的 Diffie-Hellman [DH76] 参数都编码在 KeyShare
   结构中 KeyShareEntry 的 opaque key_exchange 字段中。该 opaque 值
   包含指定组的 Diffie-Hellman 公共值(Y = g^X mod p)(组定义见
   [RFC7919]),编码为大端整数,并在左侧用零填充到 p 的字节大小。

   注意:对于给定 Diffie-Hellman 组,填充会使所有公钥具有相同长度。

   对等方 MUST 通过确保 1 < Y < p-1 来验证彼此的公钥 Y。此检查
   确保远程对等方行为正确,并且没有迫使本地系统进入一个小子群。









Rescorla                     标准化进程                      [第 50 页]


RFC 8446                           TLS                       2018 年 8 月


4.2.8.2.  ECDHE 参数

   客户端和服务器的 ECDHE 参数都编码在 KeyShare 结构中
   KeyShareEntry 的 opaque key_exchange 字段中。

   对于 secp256r1、secp384r1 和 secp521r1,其内容是以下 struct 的
   序列化值:

      struct {
          uint8 legacy_form = 4;
          opaque X[coordinate_length];
          opaque Y[coordinate_length];
      } UncompressedPointRepresentation;

   X 和 Y 分别是 x 值和 y 值按网络字节序表示的二进制形式。没有
   内部长度标记,因此每个数字表示占用的八位组数由曲线参数隐含
   决定。对于 P-256,这意味着 X 和 Y 各使用 32 个八位组,如有必要
   在左侧用零填充。对于 P-384,它们各占 48 个八位组。对于 P-521,
   它们各占 66 个八位组。

   对于曲线 secp256r1、secp384r1 和 secp521r1,对等方 MUST 通过
   确保该点是椭圆曲线上的有效点来验证彼此的公共值 Q。适当的验证
   过程定义在 [ECDSA] 第 4.3.7 节,以及替代地定义在
   [KEYAGREEMENT] 第 5.6.2.3 节。此过程包括三个步骤:
   (1) 验证 Q 不是无穷远点(O),(2) 验证对于 Q = (x, y),两个整数
   x 和 y 都处于正确区间内,(3) 确保 (x, y) 是椭圆曲线方程的正确
   解。对于这些曲线,实现者不需要验证其属于正确子群。

   对于 X25519 和 X448,公共值的内容是 [RFC7748] 中定义的相应
   函数的字节串输入和输出:X25519 为 32 字节,X448 为 56 字节。

   注意:TLS 1.3 之前的 TLS 版本允许点格式协商;TLS 1.3 移除了
   此特性,改为对每条曲线使用单一的点格式。

4.2.9.  预共享密钥交换模式

   为了使用 PSK,客户端 MUST 还发送“psk_key_exchange_modes”扩展。
   此扩展的语义是,客户端只支持将 PSK 与这些模式一起使用,这既
   限制了此 ClientHello 中所提供 PSK 的使用,也限制了服务器可能
   通过 NewSessionTicket 提供的 PSK 的使用。




Rescorla                     标准化进程                      [第 51 页]


RFC 8446                           TLS                       2018 年 8 月


   如果客户端提供“pre_shared_key”扩展,则它 MUST 提供
   “psk_key_exchange_modes”扩展。如果客户端在没有
   “psk_key_exchange_modes”扩展的情况下提供“pre_shared_key”,
   服务器 MUST 中止握手。服务器 MUST NOT 选择未被客户端列出的
   密钥交换模式。此扩展还限制了与 PSK 恢复一起使用的模式。
   服务器 SHOULD NOT 使用与所通告模式不兼容的票据发送
   NewSessionTicket;不过,如果服务器这样做,影响只是客户端尝试
   恢复会失败。

   服务器 MUST NOT 发送“psk_key_exchange_modes”扩展。

      enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;

      struct {
          PskKeyExchangeMode ke_modes<1..255>;
      } PskKeyExchangeModes;

   psk_ke:仅 PSK 密钥建立。在此模式下,服务器 MUST NOT 提供
      “key_share”值。

   psk_dhe_ke:带 (EC)DHE 密钥建立的 PSK。在此模式下,客户端和
      服务器 MUST 按第 4.2.8 节所述提供“key_share”值。

   将来分配的任何值都必须确保传输的协议消息能无歧义地标识服务器
   选择了哪种模式;目前,这是通过 ServerHello 中是否存在
   “key_share”来指明的。

4.2.10.  Early Data 指示

   当使用 PSK 且该 PSK 允许 early data 时,客户端可以在其第一趟
   消息中发送 Application Data。如果客户端选择这样做,它 MUST
   同时提供“pre_shared_key”和“early_data”扩展。

   此扩展的“extension_data”字段包含一个“EarlyDataIndication”值。












Rescorla                     标准化进程                      [第 52 页]


RFC 8446                           TLS                       2018 年 8 月


      struct {} Empty;

      struct {
          select (Handshake.msg_type) {
              case new_session_ticket:   uint32 max_early_data_size;
              case client_hello:         Empty;
              case encrypted_extensions: Empty;
          };
      } EarlyDataIndication;

   关于 max_early_data_size 字段的使用细节,见第 4.6.1 节。

   0-RTT 数据的参数(版本、对称密码套件、应用层协议协商(ALPN)
   [RFC7301] 协议等)是与所使用 PSK 关联的参数。对于外部提供的
   PSK,关联值是随密钥一起提供的值。对于通过 NewSessionTicket
   消息建立的 PSK,关联值是在建立该 PSK 的连接中协商的值。
   用于加密 early data 的 PSK MUST 是客户端“pre_shared_key”扩展中
   列出的第一个 PSK。

   对于通过 NewSessionTicket 提供的 PSK,服务器 MUST 验证所选
   PSK identity 的票据年龄(通过从 PskIdentity.obfuscated_ticket_age
   中减去 ticket_age_add 后对 2^32 取模计算)是否在票据签发以来
   时间的一个小容差范围内(见第 8 节)。如果不在范围内,
   服务器 SHOULD 继续握手但拒绝 0-RTT,并且 SHOULD NOT 采取任何
   其他假定此 ClientHello 是新鲜的操作。

   第一趟发送的 0-RTT 消息与其他趟中发送的同类型消息(handshake
   和 application_data)具有相同的(加密)内容类型,但它们受不同
   密钥保护。收到服务器的 Finished 消息后,如果服务器已接受
   early data,则会发送 EndOfEarlyData 消息以指示密钥更改。此消息
   将使用 0-RTT 流量密钥加密。













Rescorla                     标准化进程                      [第 53 页]


RFC 8446                           TLS                       2018 年 8 月


   收到“early_data”扩展的服务器 MUST 以以下三种方式之一行事:

   -  忽略该扩展并返回常规 1-RTT 响应。随后,服务器尝试使用握手
      流量密钥对收到的记录解除保护,丢弃解除保护失败的记录
      (最多到配置的 max_early_data_size),从而跳过 early data。
      一旦某条记录成功解除保护,它就被视为客户端第二趟的开始,
      服务器按普通 1-RTT 握手继续进行。

   -  通过以 HelloRetryRequest 响应,请求客户端发送另一个
      ClientHello。客户端 MUST NOT 在其后续 ClientHello 中包含
      “early_data”扩展。随后,服务器通过跳过所有外部内容类型为
      “application_data”(表示它们已加密)的记录来忽略 early data,
      最多到配置的 max_early_data_size。

   -  在 EncryptedExtensions 中返回自己的“early_data”扩展,指明它
      打算处理 early data。服务器不可能只接受 early data 消息的
      一个子集。即使服务器发送了接受 early data 的消息,实际的
      early data 本身在服务器生成此消息时可能已经在传输中。

   为了接受 early data,服务器 MUST 已接受一个 PSK 密码套件,并
   选择了客户端“pre_shared_key”扩展中提供的第一个密钥。此外,
   它 MUST 验证以下值与所选 PSK 关联的值相同:

   -  TLS 版本号

   -  所选密码套件

   -  所选 ALPN [RFC7301] 协议(如果有)

   这些要求是使用相关 PSK 执行 1-RTT 握手所需要求的超集。对于
   外部建立的 PSK,关联值是随密钥一起提供的值。对于通过
   NewSessionTicket 消息建立的 PSK,关联值是在建立该票据的连接中
   协商的值。

   未来扩展 MUST 定义它们与 0-RTT 的交互。






Rescorla                     标准化进程                      [第 54 页]


RFC 8446                           TLS                       2018 年 8 月


   如果这些检查中的任一项失败,服务器 MUST NOT 以该扩展响应,并且
   必须使用上面列出的前两种机制之一丢弃所有第一趟数据(从而回退到
   1-RTT 或 2-RTT)。如果客户端尝试 0-RTT 握手但服务器拒绝它,
   服务器通常不会拥有 0-RTT 记录保护密钥,因此必须改用试探性解密
   (使用 1-RTT 握手密钥,或在 HelloRetryRequest 的情况下查找明文
   ClientHello)来找到第一条非 0-RTT 消息。

   如果服务器选择接受“early_data”扩展,则它在处理 early data 记录时
   MUST 遵守为所有记录规定的相同错误处理要求。具体而言,如果服务器
   在接受“early_data”扩展后无法解密 0-RTT 记录,它 MUST 按
   第 5.2 节所述,使用“bad_record_mac”告警终止连接。

   如果服务器拒绝“early_data”扩展,客户端应用 MAY 选择在握手完成后
   重新传输先前在 early data 中发送的 Application Data。注意,early
   data 的自动重传可能导致对连接状态的错误假设。例如,当协商出的
   连接选择了与 early data 所用不同的 ALPN 协议时,应用可能需要
   构造不同的消息。类似地,如果 early data 对连接状态作了任何假设,
   它可能会在握手完成后被错误发送。

   TLS 实现 SHOULD NOT 自动重新发送 early data;应用更适合决定何时
   重传是合适的。除非协商出的连接选择了相同的 ALPN 协议,否则
   TLS 实现 MUST NOT 自动重新发送 early data。

4.2.11.  预共享密钥扩展

   “pre_shared_key”扩展用于协商与 PSK 密钥建立相关联、要在给定
   握手中使用的预共享密钥 identity。













Rescorla                     标准化进程                      [第 55 页]


RFC 8446                           TLS                       2018 年 8 月


   此扩展的“extension_data”字段包含一个“PreSharedKeyExtension”值:

      struct {
          opaque identity<1..2^16-1>;
          uint32 obfuscated_ticket_age;
      } PskIdentity;

      opaque PskBinderEntry<32..255>;

      struct {
          PskIdentity identities<7..2^16-1>;
          PskBinderEntry binders<33..2^16-1>;
      } OfferedPsks;

      struct {
          select (Handshake.msg_type) {
              case client_hello: OfferedPsks;
              case server_hello: uint16 selected_identity;
          };
      } PreSharedKeyExtension;

   identity:密钥的标签。例如,一个票据(如附录 B.3.4中定义)
      或外部建立的预共享密钥标签。

   obfuscated_ticket_age:密钥年龄的混淆版本。第 4.2.11.1 节描述了
      如何为通过 NewSessionTicket 消息建立的 identity 形成该值。
      对于外部建立的 identity,SHOULD 使用 0 作为 obfuscated_ticket_age,
      并且服务器 MUST 忽略该值。

   identities:客户端愿意与服务器协商的 identity 列表。如果与
      “early_data”扩展一起发送(见第 4.2.10 节),第一个 identity
      就是用于 0-RTT 数据的 identity。

   binders:一系列 HMAC 值,identities 列表中的每个值对应一个,
      且顺序相同,按下文所述计算。

   selected_identity:服务器选择的 identity,表示为客户端列表中
      identities 的(从 0 开始的)索引。

   每个 PSK 都与单个 Hash 算法关联。对于通过票据机制
   (第 4.6.1 节)建立的 PSK,这是建立该票据的连接上的 KDF Hash
   算法。对于外部建立的 PSK,Hash 算法 MUST 在



Rescorla                     标准化进程                      [第 56 页]


RFC 8446                           TLS                       2018 年 8 月


   PSK 建立时设置;如果未定义此类算法,则默认为 SHA-256。服务器
   MUST 确保它选择兼容的 PSK(如果有)和密码套件。

   在 TLS 1.3 之前的 TLS 版本中,服务器名称标识(SNI)值意图与
   会话关联([RFC6066] 第 3 节),并要求服务器强制执行与会话关联
   的 SNI 值与恢复握手中指定的 SNI 值匹配。然而,实际上,实现对于
   它们会使用两个所提供 SNI 值中的哪一个并不一致,导致一致性要求
   事实上由客户端强制执行。在 TLS 1.3 中,SNI 值始终在恢复握手中
   显式指定,服务器不需要将 SNI 值与票据关联。不过,客户端 SHOULD
   将 SNI 与 PSK 一起存储,以满足第 4.6.1 节的要求。

   实现者注意:当会话恢复是 PSK 的主要用例时,实现 PSK/密码套件
   匹配要求的最直接方式是先协商密码套件,然后排除任何不兼容的
   PSK。任何未知 PSK(例如,不在 PSK 数据库中或使用未知密钥加密
   的 PSK)SHOULD 直接忽略。如果找不到可接受的 PSK,服务器 SHOULD
   在可能时执行非 PSK 握手。如果向后兼容性很重要,客户端提供的、
   外部建立的 PSK SHOULD 影响密码套件选择。

   在接受 PSK 密钥建立之前,服务器 MUST 验证对应的 binder 值
   (见下方第 4.2.11.2 节)。如果该值不存在或验证失败,服务器
   MUST 中止握手。服务器 SHOULD NOT 尝试验证多个 binder;相反,它们
   SHOULD 选择单个 PSK,并且只验证与该 PSK 对应的 binder。关于此
   要求的安全理由,见第 8.2 节附录 E.6。为了接受 PSK
   密钥建立,服务器发送“pre_shared_key”扩展以指示所选 identity。

   客户端 MUST 验证服务器的 selected_identity 在客户端提供的范围内,
   服务器选择了一个指示与该 PSK 关联 Hash 的密码套件,并且在
   ClientHello“psk_key_exchange_modes”扩展要求时存在服务器
   “key_share”扩展。如果这些值不一致,客户端 MUST 使用
   “illegal_parameter”告警中止握手。







Rescorla                     标准化进程                      [第 57 页]


RFC 8446                           TLS                       2018 年 8 月


   如果服务器提供“early_data”扩展,客户端 MUST 验证服务器的
   selected_identity 为 0。如果返回任何其他值,客户端 MUST 使用
   “illegal_parameter”告警中止握手。

   “pre_shared_key”扩展 MUST 是 ClientHello 中的最后一个扩展
   (这有助于如下所述的实现)。服务器 MUST 检查它是最后一个扩展,
   否则使用“illegal_parameter”告警使握手失败。

4.2.11.1.  票据年龄

   客户端对票据年龄的看法是自收到 NewSessionTicket 消息以来经过的
   时间。客户端 MUST NOT 尝试使用年龄大于随票据提供的
   “ticket_lifetime”值的票据。每个 PskIdentity 的
   “obfuscated_ticket_age”字段包含票据年龄的混淆版本,其形成方式是
   取以毫秒为单位的年龄,并加上票据中包含的“ticket_age_add”值
   (见第 4.6.1 节),再对 2^32 取模。除非票据被重用,否则此
   加法会防止被动观察者关联连接。注意,NewSessionTicket 消息中的
   “ticket_lifetime”字段以秒为单位,而“obfuscated_ticket_age”以
   毫秒为单位。因为票据生命周期被限制为一周,所以 32 位足以表示
   任何可信的年龄,即使以毫秒计也是如此。

4.2.11.2.  PSK Binder

   PSK binder 值在 PSK 与当前握手之间形成绑定,也在生成该 PSK 的
   握手(如果通过 NewSessionTicket 消息生成)与当前握手之间形成
   绑定。binders 列表中的每个条目都计算为一个 HMAC,覆盖包含部分
   ClientHello 的 transcript 哈希(见第 4.4.1 节),直到并包括
   PreSharedKeyExtension.identities 字段。也就是说,它包含整个
   ClientHello,但不包含 binders 列表本身。消息的长度字段(包括
   总长度、扩展块长度以及“pre_shared_key”扩展长度)都设置得好像
   存在正确长度的 binder 一样。

   PskBinderEntry 的计算方式与 Finished 消息(第 4.4.4 节)相同,
   但 BaseKey 是通过密钥调度从所提供的对应 PSK 派生出的 binder_key
   (见第 7.1 节)。







Rescorla                     标准化进程                      [第 58 页]


RFC 8446                           TLS                       2018 年 8 月


   如果握手包含 HelloRetryRequest,则初始 ClientHello 和
   HelloRetryRequest 会与新的 ClientHello 一起包含在 transcript 中。
   例如,如果客户端发送 ClientHello1,其 binder 将基于以下内容计算:

      Transcript-Hash(Truncate(ClientHello1))

   其中 Truncate() 从 ClientHello 中移除 binders 列表。

   如果服务器以 HelloRetryRequest 响应,随后客户端发送
   ClientHello2,则其 binder 将基于以下内容计算:

      Transcript-Hash(ClientHello1,
                      HelloRetryRequest,
                      Truncate(ClientHello2))

   完整的 ClientHello1/ClientHello2 会包含在所有其他握手哈希计算中。
   注意,在第一趟中,Truncate(ClientHello1) 会被直接哈希;但在第二
   趟中,ClientHello1 会先被哈希,然后作为“message_hash”消息重新
   注入,如第 4.4.1 节所述。

4.2.11.3.  处理顺序

   允许客户端“流式”发送 0-RTT 数据,直到收到服务器的 Finished 后,
   才发送 EndOfEarlyData 消息,然后发送握手的其余部分。为了避免
   死锁,在接受“early_data”时,服务器 MUST 处理客户端的 ClientHello,
   然后立即发送自己的一趟消息,而不是等待客户端的 EndOfEarlyData
   消息之后才发送其 ServerHello。

4.3.  服务器参数

   服务器接下来的两条消息 EncryptedExtensions 和 CertificateRequest
   包含来自服务器的信息,这些信息决定握手的其余部分。这些消息使用
   从 server_handshake_traffic_secret 派生的密钥加密。













Rescorla                     标准化进程                      [第 59 页]


RFC 8446                           TLS                       2018 年 8 月


4.3.1.  Encrypted Extensions

   在所有握手中,服务器 MUST 在 ServerHello 消息之后立即发送
   EncryptedExtensions 消息。这是第一条使用从
   server_handshake_traffic_secret 派生的密钥加密的消息。

   EncryptedExtensions 消息包含可以受保护的扩展,即任何不需要用于
   建立密码上下文、但也不与单个证书关联的扩展。客户端 MUST 检查
   EncryptedExtensions 中是否存在任何被禁止的扩展,如果发现任何此类
   扩展,MUST 使用“illegal_parameter”告警中止握手。

   此消息的结构:

      struct {
          Extension extensions<0..2^16-1>;
      } EncryptedExtensions;

   extensions:扩展列表。更多信息见第 4.2 节中的表。

4.3.2.  Certificate Request

   使用证书进行认证的服务器 MAY 可选地向客户端请求证书。如果发送
   此消息,它 MUST 跟在 EncryptedExtensions 之后。

   此消息的结构:

      struct {
          opaque certificate_request_context<0..2^8-1>;
          Extension extensions<2..2^16-1>;
      } CertificateRequest;
















Rescorla                     标准化进程                      [第 60 页]


RFC 8446                           TLS                       2018 年 8 月


   certificate_request_context:一个 opaque 字符串,用于标识证书请求,
      并将在客户端的 Certificate 消息中被回显。certificate_request_context
      MUST 在此连接的作用域内唯一(从而防止客户端 CertificateVerify
      消息被重放)。除非用于第 4.6.2 节中描述的握手后认证交换,
      否则此字段 SHALL 为零长度。在请求握手后认证时,服务器 SHOULD
      使该上下文对客户端不可预测(例如,通过随机生成),以防止临时
      访问客户端私钥的攻击者预先计算有效的 CertificateVerify 消息。

   extensions:一组描述所请求证书参数的扩展。MUST 指定
      “signature_algorithms”扩展;如果为此消息定义了其他扩展,也可
      可选包含。客户端 MUST 忽略未识别的扩展。

   在 TLS 先前版本中,CertificateRequest 消息携带服务器会接受的
   签名算法和证书颁发机构列表。在 TLS 1.3 中,前者通过发送
   “signature_algorithms”和可选的“signature_algorithms_cert”扩展来
   表达。后者通过发送“certificate_authorities”扩展来表达(见
   第 4.2.4 节)。

   使用 PSK 进行认证的服务器 MUST NOT 在主握手中发送
   CertificateRequest 消息,不过如果客户端已经发送“post_handshake_auth”
   扩展(见第 4.2.6 节),它们 MAY 在握手后认证中发送该消息
   (见第 4.6.2 节)。

4.4.  认证消息第 2 节所述,TLS 通常使用一组通用消息来进行认证、密钥确认
   和握手完整性:Certificate、CertificateVerify 和 Finished。
   (PSK binder 也以类似方式执行密钥确认。)这三条消息总是作为
   其握手趟中的最后几条消息发送。Certificate 和 CertificateVerify
   消息只在特定情况下发送,如下文定义。Finished 消息总是作为认证块
   的一部分发送。这些消息使用从
   [sender]_handshake_traffic_secret 派生的密钥加密。








Rescorla                     标准化进程                      [第 61 页]


RFC 8446                           TLS                       2018 年 8 月


   认证消息的计算都统一采用以下输入:

   -  要使用的证书和签名密钥。

   -  由要包含在 transcript 哈希中的消息集合组成的 Handshake Context。

   -  用于计算 MAC 密钥的 Base Key。

   基于这些输入,这些消息随后包含:

   Certificate:用于认证的证书,以及链中任何支持证书。注意,基于
      证书的客户端认证在 PSK 握手流程中不可用(包括 0-RTT)。

   CertificateVerify:覆盖值 Transcript-Hash(Handshake Context,
      Certificate) 的签名。

   Finished:使用从 Base Key 派生的 MAC 密钥,对值
      Transcript-Hash(Handshake Context, Certificate, CertificateVerify)
      计算的 MAC。

   下表为每种场景定义 Handshake Context 和 MAC Base Key:

   +-----------+-------------------------+-----------------------------+
   | 模式      | Handshake Context       | Base Key                    |
   +-----------+-------------------------+-----------------------------+
   | Server    | ClientHello ... later   | server_handshake_traffic_   |
   |           | of EncryptedExtensions/ | secret                      |
   |           | CertificateRequest      |                             |
   |           |                         |                             |
   | Client    | ClientHello ... later   | client_handshake_traffic_   |
   |           | of server               | secret                      |
   |           | Finished/EndOfEarlyData |                             |
   |           |                         |                             |
   | Post-     | ClientHello ... client  | client_application_traffic_ |
   | Handshake | Finished +              | secret_N                    |
   |           | CertificateRequest      |                             |
   +-----------+-------------------------+-----------------------------+









Rescorla                     标准化进程                      [第 62 页]


RFC 8446                           TLS                       2018 年 8 月


4.4.1.  Transcript 哈希

   TLS 中的许多密码计算都会使用 transcript 哈希。此值通过对每条
   所包含握手消息的串接进行哈希来计算,包括携带握手消息类型和
   长度字段的握手消息头,但不包括记录层头。即:

    Transcript-Hash(M1, M2, ... Mn) = Hash(M1 || M2 || ... || Mn)

   作为此通用规则的例外,当服务器以 HelloRetryRequest 响应
   ClientHello 时,ClientHello1 的值会被一种特殊的合成握手消息替换,
   该消息的握手类型为“message_hash”,并包含 Hash(ClientHello1)。
   即:

  Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) =
      Hash(message_hash ||        /* Handshake type */
           00 00 Hash.length  ||  /* Handshake message length (bytes) */
           Hash(ClientHello1) ||  /* Hash of ClientHello1 */
           HelloRetryRequest  || ... || Mn)

   这种构造的原因是,允许服务器通过只在 cookie 中存储 ClientHello1
   的哈希来执行无状态 HelloRetryRequest,而不需要导出整个中间哈希
   状态(见第 4.2.2 节)。

   为具体起见,transcript 哈希始终取自以下握手消息序列,从第一个
   ClientHello 开始,并只包含已发送的消息:ClientHello、
   HelloRetryRequest、ClientHello、ServerHello、EncryptedExtensions、
   server CertificateRequest、server Certificate、server
   CertificateVerify、server Finished、EndOfEarlyData、client
   Certificate、client CertificateVerify、client Finished。

   一般而言,实现可以通过基于协商出的哈希保留一个运行中的
   transcript 哈希值来实现 transcript。不过请注意,后续握手后认证
   彼此不包含,只包含直到主握手结束的消息。












Rescorla                     标准化进程                      [第 63 页]


RFC 8446                           TLS                       2018 年 8 月


4.4.2.  Certificate

   此消息将端点的证书链传达给对等方。

   只要协定的密钥交换方法使用证书进行认证,服务器 MUST 发送
   Certificate 消息(这包括本文档中定义的除 PSK 之外的所有密钥
   交换方法)。

   当且仅当服务器已通过 CertificateRequest 消息(第 4.3.2 节)
   请求客户端认证时,客户端 MUST 发送 Certificate 消息。如果服务器
   请求客户端认证但没有合适的证书可用,客户端 MUST 发送一个不包含
   证书的 Certificate 消息(即“certificate_list”字段长度为 0)。
   无论 Certificate 消息是否为空,都 MUST 发送 Finished 消息。

   此消息的结构:

      enum {
          X509(0),
          RawPublicKey(2),
          (255)
      } CertificateType;

      struct {
          select (certificate_type) {
              case RawPublicKey:
                /* From RFC 7250 ASN.1_subjectPublicKeyInfo */
                opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

              case X509:
                opaque cert_data<1..2^24-1>;
          };
          Extension extensions<0..2^16-1>;
      } CertificateEntry;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          CertificateEntry certificate_list<0..2^24-1>;
      } Certificate;










Rescorla                     标准化进程                      [第 64 页]


RFC 8446                           TLS                       2018 年 8 月


   certificate_request_context:如果此消息是对 CertificateRequest 的
      响应,则为该消息中的 certificate_request_context 值。否则
      (在服务器认证的情况下),此字段 SHALL 为零长度。

   certificate_list:CertificateEntry 结构的序列(链),每个结构包含
      一个证书和一组扩展。

   extensions:CertificateEntry 的一组扩展值。“Extension”格式在
      第 4.2 节中定义。目前服务器证书的有效扩展包括 OCSP Status
      扩展 [RFC6066] 和 SignedCertificateTimestamp 扩展 [RFC6962];
      未来也可以为此消息定义扩展。服务器的 Certificate 消息中的
      扩展 MUST 对应于 ClientHello 消息中的扩展。客户端的 Certificate
      消息中的扩展 MUST 对应于服务器 CertificateRequest 消息中的扩展。
      如果某个扩展适用于整个链,则它 SHOULD 包含在第一个
      CertificateEntry 中。

   如果未在 EncryptedExtensions 中协商对应的证书类型扩展
   (“server_certificate_type”或“client_certificate_type”),或协商了
   X.509 证书类型,则每个 CertificateEntry 都包含一个 DER 编码的
   X.509 证书。发送方的证书 MUST 位于列表中的第一个 CertificateEntry。
   后续每个证书 SHOULD 直接认证它前面的那个证书。由于证书验证要求
   信任锚独立分发,因此指定信任锚的证书 MAY 从链中省略,前提是
   已知受支持的对等方拥有任何被省略的证书。

   注意:在 TLS 1.3 之前,“certificate_list”排序要求每个证书认证
   紧接在它前面的证书;然而,一些实现允许一定灵活性。服务器有时会
   出于过渡目的同时发送当前中间证书和已弃用的中间证书,其他服务器
   则只是配置错误,但这些情况仍可被正确验证。为了最大兼容性,所有
   实现 SHOULD 准备好处理来自任何 TLS 版本的潜在多余证书和任意排序,
   但端实体证书例外,它 MUST 位于第一位。

   如果协商了 RawPublicKey 证书类型,则 certificate_list MUST 包含
   不超过一个 CertificateEntry,该条目包含如 [RFC7250] 第 3 节中
   定义的 ASN1_subjectPublicKeyInfo 值。




Rescorla                     标准化进程                      [第 65 页]


RFC 8446                           TLS                       2018 年 8 月


   OpenPGP 证书类型 [RFC6091] MUST NOT 与 TLS 1.3 一起使用。

   服务器的 certificate_list MUST 始终非空。如果客户端没有适当的
   证书可用于响应服务器的认证请求,它将发送空的 certificate_list。

4.4.2.1.  OCSP 状态和 SCT 扩展

   [RFC6066] 和 [RFC6961] 提供了用于协商服务器向客户端发送 OCSP
   响应的扩展。在 TLS 1.2 及以下版本中,服务器以空扩展作为响应来
   指明已协商此扩展,并且 OCSP 信息承载在 CertificateStatus 消息中。
   在 TLS 1.3 中,服务器的 OCSP 信息承载在包含相关证书的
   CertificateEntry 中的扩展里。具体而言,来自服务器的“status_request”
   扩展的主体 MUST 是 [RFC6066] 中定义的 CertificateStatus 结构,
   并按 [RFC6960] 中的定义解释。

   注意:status_request_v2 扩展 [RFC6961] 已弃用。TLS 1.3 服务器在
   处理 ClientHello 消息时 MUST NOT 根据其存在或其中的信息采取行动;
   特别是,它们 MUST NOT 在 EncryptedExtensions、CertificateRequest
   或 Certificate 消息中发送 status_request_v2 扩展。TLS 1.3 服务器
   MUST 能够处理包含该扩展的 ClientHello 消息,因为希望在早期协议
   版本中使用它的客户端 MAY 发送该扩展。

   服务器 MAY 通过在其 CertificateRequest 消息中发送空的
   “status_request”扩展,请求客户端随其证书提供 OCSP 响应。如果
   客户端选择发送 OCSP 响应,则其“status_request”扩展的主体 MUST
   是 [RFC6066] 中定义的 CertificateStatus 结构。

   类似地,[RFC6962] 提供了一种机制,使服务器在 TLS 1.2 及以下
   版本中将签名证书时间戳(SCT)作为 ServerHello 中的扩展发送。
   在 TLS 1.3 中,服务器的 SCT 信息承载在 CertificateEntry 中的扩展里。













Rescorla                     标准化进程                      [第 66 页]


RFC 8446                           TLS                       2018 年 8 月


4.4.2.2.  服务器证书选择

   以下规则适用于服务器发送的证书:

   -  证书类型 MUST 是 X.509v3 [RFC5280],除非显式协商为其他类型
      (例如 [RFC7250])。

   -  服务器端实体证书的公钥(以及相关限制)MUST 与客户端
      “signature_algorithms”扩展中所选认证算法兼容(目前为 RSA、
      ECDSA 或 EdDSA)。

   -  证书 MUST 允许将密钥用于签名(即,如果存在 Key Usage 扩展,
      digitalSignature 位 MUST 被设置),并使用客户端
      “signature_algorithms”/“signature_algorithms_cert”扩展中指示的
      签名方案(见第 4.2.3 节)。

   -  “server_name”[RFC6066] 和“certificate_authorities”扩展用于
      指导证书选择。由于服务器 MAY 要求存在“server_name”扩展,
      客户端在适用时 SHOULD 发送此扩展。

   如果服务器能够提供这样的链,则服务器提供的所有证书 MUST 由客户端
   通告的签名算法签名(见第 4.2.3 节)。自签名证书或预期为
   信任锚的证书不会作为链的一部分进行验证,因此 MAY 使用任何算法
   签名。

   如果服务器无法生成只通过所指示受支持算法签名的证书链,则它
   SHOULD 通过向客户端发送自己选择的证书链来继续握手,该链可包含
   未知是否被客户端支持的算法。此回退链通常 SHOULD NOT 使用已弃用的
   SHA-1 哈希算法,但如果客户端的通告允许,则 MAY 使用;否则 MUST NOT
   使用。

   如果客户端无法使用所提供的证书构造可接受的链,并决定中止握手,
   则它 MUST 使用适当的证书相关告警中止握手(默认情况下为
   “unsupported_certificate”;更多信息见第 6.2 节)。

   如果服务器有多个证书,它会根据上述标准选择其中之一(此外还会
   考虑其他标准,例如传输层端点、本地配置和偏好)。





Rescorla                     标准化进程                      [第 67 页]


RFC 8446                           TLS                       2018 年 8 月


4.4.2.3.  客户端证书选择

   以下规则适用于客户端发送的证书:

   -  证书类型 MUST 是 X.509v3 [RFC5280],除非显式协商为其他类型
      (例如 [RFC7250])。

   -  如果 CertificateRequest 消息中存在“certificate_authorities”
      扩展,则证书链中至少一个证书 SHOULD 由所列 CA 之一签发。

   -  证书 MUST 使用可接受的签名算法签名,如第 4.3.2 节所述。
      注意,这放宽了 TLS 先前版本中对证书签名算法的约束。

   -  如果 CertificateRequest 消息包含非空“oid_filters”扩展,则
      端实体证书 MUST 与客户端识别的扩展 OID 匹配,如第 4.2.5 节
      所述。

4.4.2.4.  接收 Certificate 消息

   一般而言,详细的证书验证过程不属于 TLS 的范围(见 [RFC5280])。
   本节提供 TLS 特定要求。

   如果服务器提供空的 Certificate 消息,客户端 MUST 使用
   “decode_error”告警中止握手。

   如果客户端没有发送任何证书(即,它发送空的 Certificate 消息),
   服务器 MAY 酌情选择在没有客户端认证的情况下继续握手,或使用
   “certificate_required”告警中止握手。此外,如果证书链的某个方面
   不可接受(例如,它不是由已知、受信任的 CA 签名),服务器 MAY
   酌情选择继续握手(将客户端视为未认证)或中止握手。

   任何端点如果收到它需要使用任何采用 MD5 哈希的签名算法来验证的
   证书,MUST 使用“bad_certificate”告警中止握手。SHA-1 已弃用,
   并且 RECOMMENDED:任何端点如果收到它需要使用任何采用 SHA-1 哈希
   的签名算法来验证的证书,应使用“bad_certificate”告警中止握手。
   为清楚起见,这意味着端点可以为自签名证书或信任锚接受这些算法。



Rescorla                     标准化进程                      [第 68 页]


RFC 8446                           TLS                       2018 年 8 月


   RECOMMENDED 所有端点尽快过渡到 SHA-256 或更强算法,以保持与当前
   正在逐步淘汰 SHA-1 支持的实现的互操作性。

   注意,包含某种签名算法密钥的证书 MAY 使用不同的签名算法签名
   (例如,使用 ECDSA 密钥对 RSA 密钥签名)。

4.4.3.  Certificate Verify

   此消息用于提供明确证明,表明端点拥有与其证书对应的私钥。
   CertificateVerify 消息还为截至此时的握手提供完整性。服务器在
   通过证书进行认证时 MUST 发送此消息。客户端在通过证书进行认证时
   (即 Certificate 消息非空时)MUST 发送此消息。发送时,此消息
   MUST 紧接在 Certificate 消息之后,并紧接在 Finished 消息之前出现。

   此消息的结构:

      struct {
          SignatureScheme algorithm;
          opaque signature<0..2^16-1>;
      } CertificateVerify;

   algorithm 字段指定所使用的签名算法(此类型的定义见第 4.2.3 节)。
   signature 是使用该算法的数字签名。签名覆盖的内容是第 4.4.1 节
   中描述的哈希输出,即:

      Transcript-Hash(Handshake Context, Certificate)

   然后,对以下内容的串接计算数字签名:

   -  由八位组 32(0x20)重复 64 次组成的字符串

   -  上下文字符串

   -  作为分隔符的单个 0 字节

   -  要签名的内容







Rescorla                     标准化进程                      [第 69 页]


RFC 8446                           TLS                       2018 年 8 月


   此结构旨在防止针对 TLS 先前版本的一种攻击,在该攻击中,
   ServerKeyExchange 格式意味着攻击者可以获得一条带有自选 32 字节
   前缀(ClientHello.random)的消息签名。初始 64 字节填充会清除
   该前缀以及服务器控制的 ServerHello.random。

   服务器签名的上下文字符串是
   “TLS 1.3, server CertificateVerify”。客户端签名的上下文字符串是
   “TLS 1.3, client CertificateVerify”。它用于在不同上下文中生成的
   签名之间提供分离,有助于抵御潜在的跨协议攻击。

   例如,如果 transcript 哈希为 32 字节的 01(此长度对 SHA-256
   有意义),则服务器 CertificateVerify 的数字签名所覆盖的内容为:

      2020202020202020202020202020202020202020202020202020202020202020
      2020202020202020202020202020202020202020202020202020202020202020
      544c5320312e332c207365727665722043657274696669636174655665726966
      79
      00
      0101010101010101010101010101010101010101010101010101010101010101

   在发送方一侧,计算 CertificateVerify 消息 signature 字段的过程
   将以下内容作为输入:

   -  数字签名所覆盖的内容

   -  与前一条消息中发送的证书对应的私有签名密钥

   如果 CertificateVerify 消息由服务器发送,签名算法 MUST 是客户端
   “signature_algorithms”扩展中提供的算法之一,除非没有不支持算法
   就无法生成有效证书链(见第 4.2.3 节)。

   如果由客户端发送,则签名中使用的签名算法 MUST 是
   CertificateRequest 消息中“signature_algorithms”扩展的
   supported_signature_algorithms 字段中存在的算法之一。

   此外,签名算法 MUST 与发送方端实体证书中的密钥兼容。无论
   “signature_algorithms”中是否出现 RSASSA-PKCS1-v1_5 算法,RSA
   签名 MUST 使用 RSASSA-PSS 算法。SHA-1 算法 MUST NOT 用于任何
   CertificateVerify 消息签名。





Rescorla                     标准化进程                      [第 70 页]


RFC 8446                           TLS                       2018 年 8 月


   本规范中的所有 SHA-1 签名算法仅定义为用于遗留证书,对
   CertificateVerify 签名无效。

   CertificateVerify 消息的接收方 MUST 验证 signature 字段。验证过程
   将以下内容作为输入:

   -  数字签名所覆盖的内容

   -  在相关 Certificate 消息中找到的端实体证书中包含的公钥

   -  在 CertificateVerify 消息的 signature 字段中收到的数字签名

   如果验证失败,接收方 MUST 使用“decrypt_error”告警终止握手。

4.4.4.  Finished

   Finished 消息是认证块中的最后一条消息。它对于提供握手认证以及
   所计算密钥的认证至关重要。

   Finished 消息的接收方 MUST 验证其内容是否正确;如果不正确,MUST
   使用“decrypt_error”告警终止连接。

   一方发送其 Finished 消息,并从对等方接收且验证 Finished 消息后,
   可以开始在连接上发送和接收 Application Data。在以下两种情形中,
   允许在收到对等方的 Finished 之前发送数据:

   1.  客户端按第 4.2.10 节所述发送 0-RTT 数据。

   2.  服务器 MAY 在发送其第一趟消息后发送数据,但由于握手尚未完成,
       它不能确信对等方的身份或其存活性(即 ClientHello 可能已被
       重放)。











Rescorla                     标准化进程                      [第 71 页]


RFC 8446                           TLS                       2018 年 8 月


   用于计算 Finished 消息的密钥,使用 HKDF(见第 7.1 节)从
   第 4.4 节中定义的 Base Key 计算而来。具体而言:

   finished_key =
       HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)

   此消息的结构:

      struct {
          opaque verify_data[Hash.length];
      } Finished;

   verify_data 值按如下方式计算:

      verify_data =
          HMAC(finished_key,
               Transcript-Hash(Handshake Context,
                               Certificate*, CertificateVerify*))

      * 仅在存在时包含。

   HMAC [RFC2104] 使用握手的 Hash 算法。如上所述,HMAC 输入通常
   可以通过运行中的哈希实现,即此时的握手哈希。

   在 TLS 的先前版本中,verify_data 始终为 12 个八位组长。在
   TLS 1.3 中,它是用于握手的 Hash 的 HMAC 输出大小。

   注意:告警和任何其他非握手记录类型都不是握手消息,不包含在
   哈希计算中。

   Finished 消息之后的任何记录 MUST 使用适当的应用流量密钥加密,
   如第 7.2 节所述。特别是,这包括服务器响应客户端 Certificate
   和 CertificateVerify 消息而发送的任何告警。

4.5.  Early Data 结束

      struct {} EndOfEarlyData;

   如果服务器在 EncryptedExtensions 中发送了“early_data”扩展,则客户端
   MUST 在收到服务器 Finished 后发送 EndOfEarlyData 消息。如果服务器
   没有在 EncryptedExtensions 中发送“early_data”扩展,则客户端
   MUST NOT 发送 EndOfEarlyData 消息。此消息指明所有 0-RTT
   application_data 消息(如果有)均已传输,并且后续



Rescorla                     标准化进程                      [第 72 页]


RFC 8446                           TLS                       2018 年 8 月


   记录受握手流量密钥保护。服务器 MUST NOT 发送此消息,收到此消息的
   客户端 MUST 使用“unexpected_message”告警终止连接。此消息使用从
   client_early_traffic_secret 派生的密钥加密。

4.6.  握手后消息

   TLS 还允许在主握手之后发送其他消息。这些消息使用握手内容类型,
   并使用适当的应用流量密钥加密。

4.6.1.  New Session Ticket 消息

   在服务器收到客户端 Finished 消息之后的任何时间,它 MAY 发送
   NewSessionTicket 消息。此消息在票据值和从恢复主秘密派生的秘密
   PSK 之间创建唯一关联(见第 7 节)。

   客户端 MAY 在将来的握手中使用此 PSK,方式是在其 ClientHello 的
   “pre_shared_key”扩展中包含票据值(第 4.2.11 节)。服务器
   MAY 在单个连接上发送多个票据,可以是连续立即发送,也可以在特定
   事件之后发送(见附录 C.4)。例如,服务器可能在握手后认证
   之后发送新票据,以封装额外的客户端认证状态。多个票据对客户端
   有多种用途,包括:

   -  打开多个并行 HTTP 连接。

   -  通过(例如)Happy Eyeballs [RFC8305] 或相关技术,在接口和
      地址族之间执行连接竞速。

   任何票据 MUST 只能使用与建立原始连接时所用 KDF 哈希算法相同的
   密码套件恢复。

   客户端 MUST 仅在新的 SNI 值对原始会话中提供的服务器证书有效时
   才恢复,并且 SHOULD 仅在 SNI 值与原始会话中使用的值匹配时恢复。
   后者是一种性能优化:通常,没有理由期望由单个证书覆盖的不同
   服务器能够接受彼此的票据;因此,在这种情况下尝试恢复会浪费一个
   一次性票据。如果提供了此类指示(外部提供或通过任何其他方式),
   客户端 MAY 使用不同的 SNI 值恢复。





Rescorla                     标准化进程                      [第 73 页]


RFC 8446                           TLS                       2018 年 8 月


   恢复时,如果向调用应用报告 SNI 值,实现 MUST 使用恢复 ClientHello
   中发送的值,而不是前一会话中发送的值。注意,如果服务器实现拒绝
   所有带有不同 SNI 值的 PSK identity,则这两个值始终相同。

   注意:虽然恢复主秘密依赖于客户端的第二趟消息,但不请求客户端
   认证的服务器 MAY 独立计算 transcript 的剩余部分,然后在发送其
   Finished 时立即发送 NewSessionTicket,而不是等待客户端 Finished。
   例如,在预期客户端并行打开多个 TLS 连接,并可从恢复握手的较低
   开销中受益的情况下,这可能是合适的。

      struct {
          uint32 ticket_lifetime;
          uint32 ticket_age_add;
          opaque ticket_nonce<0..255>;
          opaque ticket<1..2^16-1>;
          Extension extensions<0..2^16-2>;
      } NewSessionTicket;

   ticket_lifetime:以网络字节序的 32 位无符号整数表示从票据签发时间
      起计算的生命周期秒数。服务器 MUST NOT 使用任何大于 604800 秒
      (7 天)的值。零值表示该票据应立即丢弃。无论 ticket_lifetime
      如何,客户端 MUST NOT 缓存票据超过 7 天,并且 MAY 根据本地策略
      更早删除票据。服务器 MAY 将票据视为在比 ticket_lifetime 中所述
      更短的时间段内有效。

   ticket_age_add:一个安全生成的随机 32 位值,用于混淆客户端在
      “pre_shared_key”扩展中包含的票据年龄。客户端侧票据年龄与此值
      相加后对 2^32 取模,得到客户端传输的值。服务器 MUST 为其发送的
      每个票据生成新值。

   ticket_nonce:每个票据一个的值,在此连接上签发的所有票据中唯一。









Rescorla                     标准化进程                      [第 74 页]


RFC 8446                           TLS                       2018 年 8 月


   ticket:用作 PSK identity 的票据值。票据本身是一个 opaque 标签。
      它 MAY 是数据库查找键,或自加密并自认证的值。

   extensions:票据的一组扩展值。“Extension”格式在第 4.2 节中
      定义。客户端 MUST 忽略未识别的扩展。

   当前为 NewSessionTicket 定义的唯一扩展是“early_data”,表示该
   票据可用于发送 0-RTT 数据(第 4.2.10 节)。它包含以下值:

   max_early_data_size:客户端在使用此票据时允许发送的最大 0-RTT
      数据量,以字节为单位。只计算 Application Data 载荷(即明文,
      但不包括填充或内部内容类型字节)。收到超过 max_early_data_size
      字节 0-RTT 数据的服务器 SHOULD 使用“unexpected_message”告警
      终止连接。注意,由于缺少密码材料而拒绝 early data 的服务器
      将无法区分填充和内容,因此客户端 SHOULD NOT 依赖于能够在
      early data 记录中发送大量填充。

   与票据关联的 PSK 按如下方式计算:

       HKDF-Expand-Label(resumption_master_secret,
                        "resumption", ticket_nonce, Hash.length)

   由于每条 NewSessionTicket 消息的 ticket_nonce 值都不同,因此每个
   票据都会派生出不同的 PSK。

   注意,原则上可以继续签发新票据,从而无限期延长最初从初始非 PSK
   握手(该握手很可能绑定到对等方证书)派生出的密钥材料生命周期。
   RECOMMENDED 实现对这类密钥材料的总生命周期施加限制;这些限制应
   考虑对等方证书的生命周期、期间发生吊销的可能性,以及自对等方
   在线 CertificateVerify 签名以来经过的时间。

4.6.2.  握手后认证

   当客户端已发送“post_handshake_auth”扩展(见第 4.2.6 节)时,
   服务器 MAY 在握手完成后的任何时间通过发送 CertificateRequest 消息
   来请求客户端认证。客户端 MUST 以适当的认证消息作为响应(见
   第 4.4 节)。如果客户端选择进行认证,它 MUST 发送 Certificate、
   CertificateVerify、



Rescorla                     标准化进程                      [第 75 页]


RFC 8446                           TLS                       2018 年 8 月


   和 Finished。如果它拒绝,则它 MUST 发送一个不包含证书的
   Certificate 消息,随后发送 Finished。对于给定响应,客户端的所有
   消息 MUST 在网络线上连续出现,中间不得插入其他类型的消息。

   未发送“post_handshake_auth”扩展却收到 CertificateRequest 消息的
   客户端 MUST 发送“unexpected_message”致命告警。

   注意:由于客户端认证可能涉及提示用户,服务器 MUST 准备好应对
   一些延迟,包括在发送 CertificateRequest 和收到响应之间接收任意
   数量的其他消息。此外,连续收到多个 CertificateRequest 的客户端
   MAY 以与接收顺序不同的顺序响应它们(certificate_request_context
   值允许服务器消歧这些响应)。

4.6.3.  密钥和初始化向量更新

   KeyUpdate 握手消息用于指示发送方正在更新其发送密码密钥。任何
   对等方都可以在发送 Finished 消息后发送此消息。在收到 Finished
   消息之前收到 KeyUpdate 消息的实现 MUST 使用“unexpected_message”
   告警终止连接。发送 KeyUpdate 消息后,发送方 SHALL 使用下一代
   密钥发送其所有流量,该密钥按第 7.2 节所述计算。收到
   KeyUpdate 后,接收方 MUST 更新其接收密钥。

      enum {
          update_not_requested(0), update_requested(1), (255)
      } KeyUpdateRequest;

      struct {
          KeyUpdateRequest request_update;
      } KeyUpdate;

   request_update:指示 KeyUpdate 的接收方是否应以自己的 KeyUpdate
      响应。如果实现收到任何其他值,它 MUST 使用“illegal_parameter”
      告警终止连接。

   如果 request_update 字段设置为“update_requested”,则接收方 MUST
   在发送其下一条 Application Data 记录之前,发送自己的 KeyUpdate,
   并将 request_update 设置为“update_not_requested”。此机制允许任一
   端强制更新整个连接,但会导致收到



Rescorla                     标准化进程                      [第 76 页]


RFC 8446                           TLS                       2018 年 8 月


   多个 KeyUpdate 时,可用单次更新进行响应。注意,实现可能在发送
   request_update 设置为“update_requested”的 KeyUpdate 与收到对等方的
   KeyUpdate 之间收到任意数量的消息,因为这些消息可能已经在传输中。
   然而,由于发送密钥和接收密钥是从独立的流量秘密派生的,保留接收
   流量秘密不会威胁发送方更改密钥之前所发送数据的前向保密性。

   如果实现各自独立地发送自己的 KeyUpdate,且 request_update 设置为
   “update_requested”,并且它们在传输中交叉,则每一端也都会发送
   响应,结果是每一端都前进两代。

   发送方和接收方都 MUST 使用旧密钥加密其 KeyUpdate 消息。此外,
   双方都 MUST 强制要求先收到使用旧密钥的 KeyUpdate,然后才接受任何
   使用新密钥加密的消息。不这样做可能允许消息截断攻击。

5.  记录协议

   TLS 记录协议接收要传输的消息,将数据分片为可管理的块,保护记录,
   并传输结果。接收到的数据会被验证、解密、重组,然后交付给更高层
   客户端。

   TLS 记录具有类型,这允许多个更高层协议在同一记录层上复用。
   本文档指定四种内容类型:handshake、application_data、alert 和
   change_cipher_spec。change_cipher_spec 记录仅用于兼容性目的(见
   附录 D.4)。

   实现可以在第一条 ClientHello 消息已发送或接收之后、且在收到对等方
   Finished 消息之前的任何时间,收到一条未加密的 change_cipher_spec
   类型记录,其内容由单个字节值 0x01 组成,并且 MUST 直接丢弃而不做
   进一步处理。注意,此记录可能出现在握手中实现正期待受保护记录的
   位置,因此在尝试解除记录保护之前有必要检测这种情况。收到任何其他
   change_cipher_spec 值,或收到受保护的 change_cipher_spec 记录的实现
   MUST 使用“unexpected_message”告警中止握手。如果实现检测到在第一条
   ClientHello 消息之前,或在对等方 Finished 消息之后收到
   change_cipher_spec 记录,则它 MUST 被视为意外记录类型(尽管无状态
   服务器可能无法将这些情况与允许的情况区分开来)。



Rescorla                     标准化进程                      [第 77 页]


RFC 8446                           TLS                       2018 年 8 月


   实现 MUST NOT 发送本文档未定义的记录类型,除非通过某个扩展进行了
   协商。如果 TLS 实现收到意外的记录类型,它 MUST 使用
   “unexpected_message”告警终止连接。新的记录内容类型值由 IANA 在
   TLS ContentType 注册表中分配,如第 11 节所述。

5.1.  记录层

   记录层将信息块分片为 TLSPlaintext 记录,以 2^14 字节或更小的数据
   块承载数据。根据底层 ContentType 的不同,消息边界的处理方式也
   不同。任何未来的内容类型 MUST 指定适当规则。注意,这些规则比
   TLS 1.2 中强制执行的规则更严格。

   Handshake 消息 MAY 合并到单个 TLSPlaintext 记录中,或分片到多个
   记录中,前提是:

   -  Handshake 消息 MUST NOT 与其他记录类型交错。也就是说,如果一条
      handshake 消息被拆分到两个或更多记录中,则它们之间 MUST NOT
      存在任何其他记录。

   -  Handshake 消息 MUST NOT 跨越密钥更改。实现 MUST 验证密钥更改
      之前的所有消息都恰好在记录边界对齐;如果不是,则它们 MUST 使用
      “unexpected_message”告警终止连接。因为 ClientHello、EndOfEarlyData、
      ServerHello、Finished 和 KeyUpdate 消息可以紧接在密钥更改之前,
      实现 MUST 发送与记录边界对齐的这些消息。

   实现 MUST NOT 发送 Handshake 类型的零长度分片,即使这些分片包含
   填充。

   Alert 消息(第 6 节)MUST NOT 跨记录分片,并且多个 alert
   消息 MUST NOT 合并到单个 TLSPlaintext 记录中。换句话说,Alert 类型
   的记录 MUST 正好包含一条消息。

   Application Data 消息包含对 TLS 不透明的数据。Application Data
   消息始终受保护。Application Data 的零长度分片 MAY 被发送,因为
   它们可能有助于作为流量分析对抗措施。Application Data 分片 MAY
   被拆分到多个记录中,或合并到单个记录中。






Rescorla                     标准化进程                      [第 78 页]


RFC 8446                           TLS                       2018 年 8 月


      enum {
          invalid(0),
          change_cipher_spec(20),
          alert(21),
          handshake(22),
          application_data(23),
          (255)
      } ContentType;

      struct {
          ContentType type;
          ProtocolVersion legacy_record_version;
          uint16 length;
          opaque fragment[TLSPlaintext.length];
      } TLSPlaintext;

   type:用于处理所包含 fragment 的更高层协议。

   legacy_record_version:除初始 ClientHello(即不是在 HelloRetryRequest
      之后生成的 ClientHello)之外,TLS 1.3 实现生成的所有记录 MUST
      将其设置为 0x0303;对于初始 ClientHello,出于兼容性目的它 MAY
      也为 0x0301。此字段已弃用,并且 MUST 出于所有目的被忽略。
      TLS 的先前版本在某些情况下会在此字段中使用其他值。

   length:后续 TLSPlaintext.fragment 的长度(以字节计)。该长度
      MUST NOT 超过 2^14 字节。收到超过此长度记录的端点 MUST 使用
      “record_overflow”告警终止连接。

   fragment:正在传输的数据。此值是透明的,并被视为一个独立块,
      由 type 字段指定的更高层协议处理。

   本文档描述的是 TLS 1.3,它使用版本 0x0304。此版本值是历史原因
   造成的,源于 TLS 1.0 使用 0x0301、SSL 3.0 使用 0x0300。为了最大化
   向后兼容性,包含初始 ClientHello 的记录 SHOULD 使用版本 0x0301
   (反映 TLS 1.0),而包含第二个 ClientHello 或 ServerHello 的记录
   MUST 使用版本 0x0303(反映 TLS 1.2)。在协商 TLS 先前版本时,
   端点遵循附录 D中提供的过程和要求。







Rescorla                     标准化进程                      [第 79 页]


RFC 8446                           TLS                       2018 年 8 月


   当记录保护尚未启用时,TLSPlaintext 结构会直接写入网络线上。
   一旦记录保护开始,TLSPlaintext 记录会受到保护,并按下一节所述
   发送。注意,Application Data 记录 MUST NOT 在未受保护的情况下写入
   网络线(详情见第 2 节)。

5.2.  记录载荷保护

   记录保护函数将 TLSPlaintext 结构转换为 TLSCiphertext 结构。
   解除保护函数则反转此过程。与 TLS 的先前版本不同,在 TLS 1.3 中,
   所有密码都建模为“带关联数据的认证加密”(AEAD)[RFC5116]。
   AEAD 函数提供统一的加密和认证操作,将明文转换为认证密文,并能
   再转换回来。每个加密记录都由一个明文头后接一个加密主体组成,
   该主体自身包含一个类型和可选填充。

      struct {
          opaque content[TLSPlaintext.length];
          ContentType type;
          uint8 zeros[length_of_padding];
      } TLSInnerPlaintext;

      struct {
          ContentType opaque_type = application_data; /* 23 */
          ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
          uint16 length;
          opaque encrypted_record[TLSCiphertext.length];
      } TLSCiphertext;

   content:TLSPlaintext.fragment 值,包含 handshake 或 alert 消息的
      字节编码,或要发送的应用数据原始字节。

   type:TLSPlaintext.type 值,包含记录的内容类型。

   zeros:type 字段之后的明文中可以出现任意长度的一串零值字节。只要
      总大小保持在记录大小限制之内,这就为发送方提供了按所选数量对
      任何 TLS 记录进行填充的机会。更多细节见第 5.4 节Rescorla                     标准化进程                      [第 80 页]


RFC 8446                           TLS                       2018 年 8 月


   opaque_type:TLSCiphertext 记录的外层 opaque_type 字段始终设置为
      值 23(application_data),以便与习惯解析 TLS 先前版本的中间盒
      保持外部兼容。记录的实际内容类型在解密后的
      TLSInnerPlaintext.type 中找到。

   legacy_record_version:legacy_record_version 字段始终为 0x0303。
      TLS 1.3 TLSCiphertext 只会在 TLS 1.3 已协商后生成,因此不存在
      可能收到其他值的历史兼容性问题。注意,握手协议(包括
      ClientHello 和 ServerHello 消息)会认证协议版本,因此此值是
      冗余的。

   length:后续 TLSCiphertext.encrypted_record 的长度(以字节计),
      它是 content 和 padding 的长度之和,再加上内部内容类型的一个
      字节,以及 AEAD 算法添加的任何扩展。该长度 MUST NOT 超过
      2^14 + 256 字节。收到超过此长度记录的端点 MUST 使用
      “record_overflow”告警终止连接。

   encrypted_record:序列化 TLSInnerPlaintext 结构的 AEAD 加密形式。

   如 [RFC5116] 第 2.1 节所述,AEAD 算法将单个密钥、一个 nonce、
   明文以及要包含在认证检查中的“additional data”作为输入。密钥是
   client_write_key 或 server_write_key,nonce 从序列号和 client_write_iv
   或 server_write_iv 派生(见第 5.3 节),additional data 输入
   是记录头。

   即:

      additional_data = TLSCiphertext.opaque_type ||
                        TLSCiphertext.legacy_record_version ||
                        TLSCiphertext.length

   AEAD 算法的明文输入是编码后的 TLSInnerPlaintext 结构。流量密钥的
   派生在第 7.3 节中定义。

   AEAD 输出由 AEAD 加密操作的密文输出组成。由于包含
   TLSInnerPlaintext.type 和发送方提供的任何填充,明文长度大于对应的
   TLSPlaintext.length。AEAD 输出的长度通常会大于明文,但增量会随
   AEAD 算法而变化。



Rescorla                     标准化进程                      [第 81 页]


RFC 8446                           TLS                       2018 年 8 月


   由于密码可能包含填充,因此开销量可能随明文长度不同而变化。
   符号化表示为:

      AEADEncrypted =
          AEAD-Encrypt(write_key, nonce, additional_data, plaintext)

   TLSCiphertext 的 encrypted_record 字段设置为 AEADEncrypted。

   为了解密和验证,密码将密钥、nonce、additional data 和 AEADEncrypted
   值作为输入。输出要么是明文,要么是指示解密失败的错误。不存在
   单独的完整性检查。符号化表示为:

      plaintext of encrypted_record =
          AEAD-Decrypt(peer_write_key, nonce,
                       additional_data, AEADEncrypted)

   如果解密失败,接收方 MUST 使用“bad_record_mac”告警终止连接。

   TLS 1.3 中使用的 AEAD 算法 MUST NOT 产生大于 255 个八位组的扩展。
   端点如果从对等方收到 TLSCiphertext.length 大于 2^14 + 256 个八位组
   的记录,MUST 使用“record_overflow”告警终止连接。此限制源自最大
   TLSInnerPlaintext 长度 2^14 个八位组 + 1 个 ContentType 八位组 +
   最大 AEAD 扩展 255 个八位组。

5.3.  每记录 Nonce

   读记录和写记录分别维护一个 64 位序列号。读取或写入每条记录后,
   相应的序列号递增 1。每个序列号在连接开始时以及密钥更改时设置为
   零;在特定流量密钥下传输的第一条记录 MUST 使用序列号 0。

   由于序列号大小为 64 位,它们不应回绕。如果 TLS 实现需要回绕某个
   序列号,它 MUST 重新生成密钥(第 4.6.3 节)或终止连接。












Rescorla                     标准化进程                      [第 82 页]


RFC 8446                           TLS                       2018 年 8 月


   每个 AEAD 算法都会指定每记录 nonce 的可能输入长度范围,从 N_MIN
   字节到 N_MAX 字节 [RFC5116]。TLS 每记录 nonce 的长度(iv_length)
   设置为 8 字节和该 AEAD 算法的 N_MIN 中较大的一个(见
   [RFC5116] 第 4 节)。N_MAX 小于 8 字节的 AEAD 算法 MUST NOT 与
   TLS 一起使用。AEAD 构造的每记录 nonce 按如下方式形成:

   1.  64 位记录序列号以网络字节序编码,并在左侧用零填充到
       iv_length。

   2.  填充后的序列号与静态 client_write_iv 或 server_write_iv
       (取决于角色)进行异或。

   得到的量(长度为 iv_length)用作每记录 nonce。

   注意:这与 TLS 1.2 中的构造不同,TLS 1.2 指定了部分显式 nonce。

5.4.  记录填充

   所有加密 TLS 记录都可以被填充以增大 TLSCiphertext 的大小。这允许
   发送方向观察者隐藏流量大小。

   生成 TLSCiphertext 记录时,实现 MAY 选择填充。未填充记录只是填充
   长度为零的记录。填充是在加密之前附加到 ContentType 字段之后的一串
   零值字节。实现 MUST 在加密之前将填充八位组全部设置为零。

   如果发送方愿意,Application Data 记录可以包含零长度的
   TLSInnerPlaintext.content。这允许在活动存在与否可能敏感的上下文中
   生成大小可信的掩护流量。实现 MUST NOT 发送具有零长度
   TLSInnerPlaintext.content 的 Handshake 和 Alert 记录;如果收到这样的
   消息,接收实现 MUST 使用“unexpected_message”告警终止连接。











Rescorla                     标准化进程                      [第 83 页]


RFC 8446                           TLS                       2018 年 8 月


   发送的填充会由记录保护机制自动验证;成功解密
   TLSCiphertext.encrypted_record 后,接收实现从该字段末尾向开头扫描,
   直到找到一个非零八位组。此非零八位组就是消息的内容类型。选择此
   填充方案,是因为它允许将任何加密 TLS 记录填充为任意大小(从零到
   TLS 记录大小限制),而无需引入新的内容类型。该设计还强制所有填充
   八位组为零,从而允许快速检测填充错误。

   实现 MUST 将其扫描限制在 AEAD 解密返回的明文内。如果接收实现没有
   在明文中找到非零八位组,它 MUST 使用“unexpected_message”告警终止
   连接。

   填充的存在不会改变总体记录大小限制:完整编码的 TLSInnerPlaintext
   MUST NOT 超过 2^14 + 1 个八位组。如果最大分片长度被降低,例如通过
   [RFC8449] 中的 record_size_limit 扩展降低,则降低后的限制适用于
   完整明文,包括内容类型和填充。

   选择一种指示何时填充以及填充多少的填充策略是一个复杂主题,超出
   本规范范围。如果 TLS 之上的应用层协议有自己的填充,则可能更适合
   在应用层内填充 Application Data TLS 记录。不过,加密 Handshake 或
   Alert 记录的填充仍必须在 TLS 层处理。后续文档可以定义填充选择算法,
   或通过 TLS 扩展或其他方式定义填充策略请求机制。

5.5.  密钥使用限制

   在给定一组密钥下可以安全加密的明文数量存在密码学限制。
   [AEAD-LIMITS] 在假设底层原语(AES 或 ChaCha20)没有弱点的情况下
   对这些限制进行了分析。实现 SHOULD 在达到这些限制之前,按
   第 4.6.3 节所述执行密钥更新。

   对于 AES-GCM,在给定连接上最多可以加密 2^24.5 条完整大小的记录
   (约 2400 万条),同时为认证加密(AE)安全性保留约 2^-57 的安全
   裕量。对于 ChaCha20/Poly1305,记录序列号会在达到安全限制之前回绕。





Rescorla                     标准化进程                      [第 84 页]


RFC 8446                           TLS                       2018 年 8 月


6.  告警协议

   TLS 提供 Alert 内容类型来指示关闭信息和错误。与其他消息一样,
   alert 消息会按当前连接状态指定的方式加密。

   Alert 消息传达告警描述,以及一个遗留字段,该字段在 TLS 的先前
   版本中传达消息严重级别。告警分为两类:关闭告警和错误告警。在
   TLS 1.3 中,严重性隐含在所发送告警的类型中,“level”字段可以安全
   忽略。“close_notify”告警用于指示连接一个方向上的有序关闭。收到
   这样的告警后,TLS 实现 SHOULD 向应用指示数据结束。

   错误告警表示连接的中止性关闭(见第 6.2 节)。收到错误告警后,
   TLS 实现 SHOULD 向应用指示错误,并且 MUST NOT 允许在连接上发送或
   接收任何更多数据。服务器和客户端 MUST 忘记在失败连接中建立的秘密
   值和密钥,但与会话票据关联的 PSK 除外;如果可能,这些 PSK SHOULD
   被丢弃。

   第 6.2 节中列出的所有告警 MUST 以 AlertLevel=fatal 发送,并且在
   收到时无论消息中的 AlertLevel 如何,都 MUST 被视为错误告警。未知
   Alert 类型 MUST 被视为错误告警。

   注意:TLS 定义了两个通用告警(见第 6 节),用于解析消息失败
   时。收到无法按语法解析的消息(例如,长度超出消息边界或包含超出
   范围的长度)的对等方 MUST 使用“decode_error”告警终止连接。收到
   语法正确但语义无效的消息(例如,p - 1 的 DHE 份额,或无效枚举)的
   对等方 MUST 使用“illegal_parameter”告警终止连接。















Rescorla                     标准化进程                      [第 85 页]


RFC 8446                           TLS                       2018 年 8 月


      enum { warning(1), fatal(2), (255) } AlertLevel;

      enum {
          close_notify(0),
          unexpected_message(10),
          bad_record_mac(20),
          record_overflow(22),
          handshake_failure(40),
          bad_certificate(42),
          unsupported_certificate(43),
          certificate_revoked(44),
          certificate_expired(45),
          certificate_unknown(46),
          illegal_parameter(47),
          unknown_ca(48),
          access_denied(49),
          decode_error(50),
          decrypt_error(51),
          protocol_version(70),
          insufficient_security(71),
          internal_error(80),
          inappropriate_fallback(86),
          user_canceled(90),
          missing_extension(109),
          unsupported_extension(110),
          unrecognized_name(112),
          bad_certificate_status_response(113),
          unknown_psk_identity(115),
          certificate_required(116),
          no_application_protocol(120),
          (255)
      } AlertDescription;

      struct {
          AlertLevel level;
          AlertDescription description;
      } Alert;














Rescorla                     标准化进程                      [第 86 页]


RFC 8446                           TLS                       2018 年 8 月


6.1.  关闭告警

   客户端和服务器必须共享连接正在结束这一认知,以避免截断攻击。

   close_notify:此告警通知接收方,发送方不会再在此连接上发送任何
      消息。收到关闭告警后接收的任何数据 MUST 被忽略。

   user_canceled:此告警通知接收方,发送方正在因与协议失败无关的某种
      原因取消握手。如果用户在握手完成后取消操作,只需通过发送
      “close_notify”关闭连接更为合适。此告警 SHOULD 后接
      “close_notify”。此告警通常具有 AlertLevel=warning。

   任一方 MAY 通过发送“close_notify”告警来发起关闭其连接写侧。
   收到关闭告警后接收的任何数据 MUST 被忽略。如果在“close_notify”
   之前收到传输层关闭,接收方无法知道已发送的所有数据是否都已收到。

   每一方 MUST 在关闭其连接写侧之前发送“close_notify”告警,除非它
   已经发送过某个错误告警。这不会影响其连接读侧。注意,这与 TLS 1.3
   之前的 TLS 版本不同,在那些版本中,实现被要求通过丢弃待处理写入
   并立即发送自己的“close_notify”告警来响应“close_notify”。先前的
   要求可能导致读侧截断。双方在关闭其连接读侧之前无需等待收到
   “close_notify”告警,尽管这样做会引入截断的可能性。

   如果使用 TLS 的应用协议规定在 TLS 连接关闭后仍可通过底层传输承载
   任何数据,则 TLS 实现 MUST 在向应用层指示数据结束之前收到
   “close_notify”告警。本标准的任何部分都不应被理解为规定 TLS 使用
   配置文件管理其数据传输的方式,包括连接何时打开或关闭。

   注意:这里假定关闭连接写侧会在销毁传输之前可靠交付待处理数据。







Rescorla                     标准化进程                      [第 87 页]


RFC 8446                           TLS                       2018 年 8 月


6.2.  错误告警

   TLS 中的错误处理非常简单。检测到错误时,检测方会向其对等方发送
   一条消息。发送或收到致命告警消息后,双方 MUST 立即关闭连接。

   每当实现遇到致命错误条件时,它 SHOULD 发送适当的致命告警,并且
   MUST 在不发送或接收任何额外数据的情况下关闭连接。在本规范的其余
   部分中,当短语“terminate the connection”和“abort the handshake”
   在没有具体告警的情况下使用时,表示实现 SHOULD 发送下面描述中指示
   的告警。短语“terminate the connection with an X alert”和“abort the
   handshake with an X alert”表示如果实现发送任何告警,则它 MUST 发送
   告警 X。自 TLS 1.3 起,本节下面定义的所有告警以及所有未知告警都
   普遍被视为致命告警(见第 6 节)。实现 SHOULD 提供一种方法,
   便于记录告警的发送和接收。

   定义了以下错误告警:

   unexpected_message:收到不适当的消息(例如错误的握手消息、过早的
      Application Data 等)。在正确实现之间的通信中绝不应观察到此告警。

   bad_record_mac:如果收到无法解除保护的记录,则返回此告警。由于
      AEAD 算法结合了解密和验证,并且也为了避免侧信道攻击,此告警
      用于所有解除保护失败。在正确实现之间的通信中绝不应观察到此
      告警,除非消息在网络中被破坏。

   record_overflow:收到长度超过 2^14 + 256 字节的 TLSCiphertext 记录,
      或某条记录解密为超过 2^14 字节(或某个其他协商限制)的
      TLSPlaintext 记录。在正确实现之间的通信中绝不应观察到此告警,
      除非消息在网络中被破坏。

   handshake_failure:收到“handshake_failure”告警消息表示发送方无法
      在可用选项下协商出可接受的一组安全参数。

   bad_certificate:证书已损坏,包含未能正确验证的签名,等等。



Rescorla                     标准化进程                      [第 88 页]


RFC 8446                           TLS                       2018 年 8 月


   unsupported_certificate:证书属于不支持的类型。

   certificate_revoked:证书已被其签名者吊销。

   certificate_expired:证书已过期或当前无效。

   certificate_unknown:处理证书时出现某些其他(未指定)问题,使其
      不可接受。

   illegal_parameter:握手中的某个字段不正确,或与其他字段不一致。
      此告警用于符合正式协议语法但在其他方面不正确的错误。

   unknown_ca:收到有效证书链或部分证书链,但该证书未被接受,因为
      无法定位 CA 证书,或无法将其与已知信任锚匹配。

   access_denied:收到有效证书或 PSK,但在应用访问控制时,发送方决定
      不继续协商。

   decode_error:无法解码消息,因为某个字段超出指定范围或消息长度
      不正确。此告警用于消息不符合正式协议语法的错误。在正确实现
      之间的通信中绝不应观察到此告警,除非消息在网络中被破坏。

   decrypt_error:握手(非记录层)密码操作失败,包括无法正确验证签名、
      验证 Finished 消息或验证 PSK binder。

   protocol_version:对等方试图协商的协议版本可识别但不受支持(见
      附录 D)。

   insufficient_security:当协商失败特别是因为服务器要求比客户端支持的
      参数更安全的参数时,返回此告警而不是“handshake_failure”。

   internal_error:与对等方或协议正确性无关的内部错误(例如内存分配
      失败)使得无法继续。

   inappropriate_fallback:由服务器发送,以响应来自客户端的无效连接
      重试尝试(见 [RFC7507])。



Rescorla                     标准化进程                      [第 89 页]


RFC 8446                           TLS                       2018 年 8 月


   missing_extension:由端点在收到握手消息时发送,该消息不包含对于所
      提供 TLS 版本或其他协商参数而言强制发送的扩展。

   unsupported_extension:由端点在收到任何握手消息时发送,该消息包含
      已知被禁止包含在给定握手消息中的扩展,或在 ServerHello 或
      Certificate 中包含任何未先在对应 ClientHello 或 CertificateRequest
      中提供的扩展。

   unrecognized_name:由服务器在没有任何服务器由客户端通过
      “server_name”扩展提供的名称标识时发送(见 [RFC6066])。

   bad_certificate_status_response:当服务器通过“status_request”扩展提供
      无效或不可接受的 OCSP 响应时,由客户端发送(见 [RFC6066])。

   unknown_psk_identity:当希望进行 PSK 密钥建立但客户端未提供可接受的
      PSK identity 时,由服务器发送。发送此告警是 OPTIONAL;服务器
      MAY 改为选择发送“decrypt_error”告警,仅表示无效的 PSK identity。

   certificate_required:当服务器希望客户端提供证书但客户端未提供时,
      由服务器发送。

   no_application_protocol:当客户端的
      “application_layer_protocol_negotiation”扩展只通告服务器不支持的
      协议时,由服务器发送(见 [RFC7301])。

   新的 Alert 值由 IANA 按第 11 节所述分配。

7.  密码计算

   TLS 握手会建立一个或多个输入秘密,这些秘密被组合以创建实际使用的
   工作密钥材料,如下所详述。密钥派生过程同时纳入输入秘密和握手
   transcript。注意,因为握手 transcript 包含 Hello 消息中的随机值,
   所以任何给定握手都会具有不同的流量秘密,即使使用相同的输入秘密,
   例如在多个连接中使用同一个 PSK 时也是如此。








Rescorla                     标准化进程                      [第 90 页]


RFC 8446                           TLS                       2018 年 8 月


7.1.  密钥调度

   密钥派生过程使用 HKDF [RFC5869] 中为 HKDF 定义的 HKDF-Extract 和
   HKDF-Expand 函数,以及下面定义的函数:

       HKDF-Expand-Label(Secret, Label, Context, Length) =
            HKDF-Expand(Secret, HkdfLabel, Length)

       其中 HkdfLabel 指定为:

       struct {
           uint16 length = Length;
           opaque label<7..255> = "tls13 " + Label;
           opaque context<0..255> = Context;
       } HkdfLabel;

       Derive-Secret(Secret, Label, Messages) =
            HKDF-Expand-Label(Secret, Label,
                              Transcript-Hash(Messages), Hash.length)

   Transcript-Hash 和 HKDF 使用的 Hash 函数是密码套件哈希算法。
   Hash.length 是其输出长度(以字节计)。Messages 是所指示握手消息的
   串接,包括握手消息类型和长度字段,但不包括记录层头。注意,在某些
   情况下,会向 HKDF-Expand-Label 传递零长度 Context(以 "" 表示)。
   本文档中指定的标签都是 ASCII 字符串,不包含结尾 NUL 字节。

   注意:对于常见哈希函数,任何长于 12 个字符的标签都需要哈希函数的
   额外一次迭代来计算。本规范中的所有标签都已选择为适合此限制。

















Rescorla                     标准化进程                      [第 91 页]


RFC 8446                           TLS                       2018 年 8 月


   密钥使用 HKDF-Extract 和 Derive-Secret 函数从两个输入秘密派生。
   添加新秘密的一般模式是使用 HKDF-Extract,其中 Salt 是当前秘密状态,
   输入密钥材料(IKM)是要添加的新秘密。在此 TLS 1.3 版本中,两个
   输入秘密是:

   -  PSK(外部建立的预共享密钥,或从先前连接的
      resumption_master_secret 值派生)

   -  (EC)DHE 共享秘密(第 7.4 节)

   这会产生下图所示的完整密钥派生调度。在此图中,应用以下格式约定:

   -  HKDF-Extract 被画作从顶部接收 Salt 参数、从左侧接收 IKM 参数,
      其输出在底部,输出名称在右侧。

   -  Derive-Secret 的 Secret 参数由传入箭头表示。例如,Early Secret
      是用于生成 client_early_traffic_secret 的 Secret。

   -  “0”表示由 Hash.length 个字节组成、且全部设置为零的字符串。




























Rescorla                     标准化进程                      [第 92 页]


RFC 8446                           TLS                       2018 年 8 月


             0
             |
             v
   PSK ->  HKDF-Extract = Early Secret
             |
             +-----> Derive-Secret(., "ext binder" | "res binder", "")
             |                     = binder_key
             |
             +-----> Derive-Secret(., "c e traffic", ClientHello)
             |                     = client_early_traffic_secret
             |
             +-----> Derive-Secret(., "e exp master", ClientHello)
             |                     = early_exporter_master_secret
             v
       Derive-Secret(., "derived", "")
             |
             v
   (EC)DHE -> HKDF-Extract = Handshake Secret
             |
             +-----> Derive-Secret(., "c hs traffic",
             |                     ClientHello...ServerHello)
             |                     = client_handshake_traffic_secret
             |
             +-----> Derive-Secret(., "s hs traffic",
             |                     ClientHello...ServerHello)
             |                     = server_handshake_traffic_secret
             v
       Derive-Secret(., "derived", "")
             |
             v
   0 -> HKDF-Extract = Master Secret
             |
             +-----> Derive-Secret(., "c ap traffic",
             |                     ClientHello...server Finished)
             |                     = client_application_traffic_secret_0
             |
             +-----> Derive-Secret(., "s ap traffic",
             |                     ClientHello...server Finished)
             |                     = server_application_traffic_secret_0
             |
             +-----> Derive-Secret(., "exp master",
             |                     ClientHello...server Finished)
             |                     = exporter_master_secret
             |
             +-----> Derive-Secret(., "res master",
                                   ClientHello...client Finished)
                                   = resumption_master_secret




Rescorla                     标准化进程                      [第 93 页]


RFC 8446                           TLS                       2018 年 8 月


   这里的一般模式是,图左侧向下显示的秘密只是没有上下文的原始熵,
   而右侧向下显示的秘密包含 Handshake Context,因此可用于在没有额外
   上下文的情况下派生工作密钥。注意,即使使用相同秘密,对
   Derive-Secret 的不同调用也可能采用不同的 Messages 参数。在 0-RTT
   交换中,Derive-Secret 使用四个不同 transcript 调用;在仅 1-RTT
   交换中,它使用三个不同 transcript 调用。

   如果给定秘密不可用,则使用由 Hash.length 个字节组成、且全部设置为
   零的 0 值。注意,这并不意味着跳过轮次,因此如果未使用 PSK,
   Early Secret 仍将是 HKDF-Extract(0, 0)。对于 binder_key 的计算,
   外部 PSK(在 TLS 之外提供的 PSK)的标签为“ext binder”,恢复 PSK
   (作为先前握手恢复主秘密提供的 PSK)的标签为“res binder”。不同
   标签可防止一种 PSK 类型替换另一种。

   存在多个潜在的 Early Secret 值,取决于服务器最终选择哪个 PSK。
   客户端需要为每个潜在 PSK 计算一个 Early Secret;如果没有选择 PSK,
   它随后需要计算对应于零 PSK 的 Early Secret。

   一旦从给定秘密派生的所有值都已计算完成,该秘密 SHOULD 被擦除。

7.2.  更新流量秘密

   一旦握手完成,任一方都可以使用第 4.6.3 节中定义的 KeyUpdate
   握手消息来更新其发送流量密钥。下一代流量密钥通过按本节所述从
   client_/server_application_traffic_secret_N 生成
   client_/server_application_traffic_secret_N+1,然后按第 7.3 节
   所述重新派生流量密钥来计算。

   下一代 application_traffic_secret 按如下方式计算:

       application_traffic_secret_N+1 =
           HKDF-Expand-Label(application_traffic_secret_N,
                             "traffic upd", "", Hash.length)

   一旦 client_/server_application_traffic_secret_N+1 及其关联流量密钥
   已计算完成,实现 SHOULD 删除 client_/server_application_traffic_secret_N
   及其关联流量密钥。




Rescorla                     标准化进程                      [第 94 页]


RFC 8446                           TLS                       2018 年 8 月


7.3.  流量密钥计算

   流量密钥材料由以下输入值生成:

   -  秘密值

   -  表示正在生成的具体值的用途值

   -  正在生成的密钥长度

   流量密钥材料使用以下方式从输入流量秘密值生成:

   [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
   [sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)

   [sender] 表示发送方。每种记录类型的 Secret 值如下表所示。

       +-------------------+---------------------------------------+
       | 记录类型          | Secret                                |
       +-------------------+---------------------------------------+
       | 0-RTT Application | client_early_traffic_secret           |
       |                   |                                       |
       | Handshake         | [sender]_handshake_traffic_secret     |
       |                   |                                       |
       | Application Data  | [sender]_application_traffic_secret_N |
       +-------------------+---------------------------------------+

   每当底层 Secret 改变时,所有流量密钥材料都会重新计算(例如,从握手
   密钥切换到 Application Data 密钥时,或在密钥更新时)。

7.4.  (EC)DHE 共享秘密计算

7.4.1.  有限域 Diffie-Hellman

   对于有限域组,执行常规 Diffie-Hellman [DH76] 计算。协商出的密钥
   (Z)通过以大端形式编码并在左侧用零填充到素数大小,转换为字节串。
   此字节串按上文指定用作密钥调度中的共享秘密。

   注意,此构造不同于 TLS 先前版本,后者会移除前导零。





Rescorla                     标准化进程                      [第 95 页]


RFC 8446                           TLS                       2018 年 8 月


7.4.2.  椭圆曲线 Diffie-Hellman

   对于 secp256r1、secp384r1 和 secp521r1,ECDH 计算(包括参数和密钥
   生成以及共享秘密计算)按照 [IEEE1363] 执行,使用 ECKAS-DH1
   方案,并以恒等映射作为密钥派生函数(KDF),从而共享秘密是 ECDH
   共享秘密椭圆曲线点的 x 坐标,表示为八位组字符串。注意,由 FE2OSP
   (Field Element to Octet String Conversion Primitive)输出的这个
   八位组字符串(IEEE 1363 术语中的“Z”)对于任何给定域都有恒定
   长度;此八位组字符串中出现的前导零 MUST NOT 被截断。

   (注意,这里使用恒等 KDF 是一个技术细节。完整图景是,ECDH 实际上
   与非平凡 KDF 一起使用,因为 TLS 不会直接将此秘密用于计算其他秘密
   之外的任何用途。)

   对于 X25519 和 X448,ECDH 计算如下:

   -  放入 KeyShareEntry.key_exchange 结构中的公钥,是将 ECDH 标量乘法
      函数应用于适当长度的秘密密钥(作为标量输入)和标准公共基点
      (作为 u 坐标点输入)的结果。

   -  ECDH 共享秘密是将 ECDH 标量乘法函数应用于秘密密钥(作为标量
      输入)和对等方公钥(作为 u 坐标点输入)的结果。输出原样使用,
      不进行处理。

   对于这些曲线,实现 SHOULD 使用 [RFC7748] 中指定的方法计算
   Diffie-Hellman 共享秘密。实现 MUST 检查计算出的 Diffie-Hellman
   共享秘密是否为全零值,如是则中止,如 [RFC7748] 第 6 节所述。
   如果实现者使用这些椭圆曲线的替代实现,则他们 SHOULD 执行
   [RFC7748] 第 7 节中指定的额外检查。













Rescorla                     标准化进程                      [第 96 页]


RFC 8446                           TLS                       2018 年 8 月


7.5.  导出器

   [RFC5705] 按 TLS 伪随机函数(PRF)定义 TLS 的密钥材料导出器。
   本文档用 HKDF 替换 PRF,因此需要一种新的构造。导出器接口保持相同。

   导出器值按如下方式计算:

   TLS-Exporter(label, context_value, key_length) =
       HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
                         "exporter", Hash(context_value), key_length)

   其中 Secret 是 early_exporter_master_secret 或 exporter_master_secret。
   除非应用显式指定,否则实现 MUST 使用 exporter_master_secret。
   early_exporter_master_secret 定义为用于需要为 0-RTT 数据使用导出器
   的场景。RECOMMENDED 为 early exporter 提供单独接口;这避免导出器
   用户在想要常规导出器时意外使用 early exporter,或反之。

   如果未提供上下文,则 context_value 为零长度。因此,不提供上下文与
   提供空上下文会计算出相同值。这与 TLS 先前版本不同,在先前版本中,
   空上下文与缺失上下文会产生不同输出。截至本文档发布时,没有已分配
   的导出器标签同时带上下文和不带上下文使用。未来规范 MUST NOT 定义
   允许同一标签同时使用空上下文和无上下文的导出器用法。导出器的新
   用法 SHOULD 在所有导出器计算中提供上下文,尽管该值可以为空。

   导出器标签格式的要求定义在 [RFC5705] 第 4 节中。
















Rescorla                     标准化进程                      [第 97 页]


RFC 8446                           TLS                       2018 年 8 月


8.  0-RTT 与反重放第 2.3 节附录 E.5所述,TLS 不为 0-RTT 数据提供内在
   重放保护。需要关注两种潜在威胁:

   -  网络攻击者通过简单复制一趟 0-RTT 数据来发起重放攻击。

   -  网络攻击者利用客户端重试行为,安排服务器接收应用消息的多个
      副本。由于重视健壮性的客户端会通过尝试重试请求来响应网络错误,
      此威胁在某种程度上已经存在。然而,对于不维护全局一致服务器状态
      的任何服务器系统,0-RTT 增加了一个额外维度。具体而言,如果服务器
      系统有多个区域,其中来自区域 A 的票据不会在区域 B 被接受,则攻击者
      可以将原本发往 A 的 ClientHello 和 early data 复制到 A 和 B。
      在 A,数据将在 0-RTT 中被接受;但在 B,服务器会拒绝 0-RTT 数据,
      而是强制执行完整握手。如果攻击者阻止来自 A 的 ServerHello,则客户端
      将与 B 完成握手,并且可能重试请求,导致整个服务器系统上发生重复。

   第一类攻击可以通过共享状态来防止,以保证 0-RTT 数据最多只被接受
   一次。服务器 SHOULD 通过实现本节中描述的方法之一或等效方式来提供
   这种级别的重放安全性。然而,可以理解的是,由于操作方面的考量,并非
   所有部署都会维护这种级别的状态。因此,在正常操作中,客户端不会知道
   服务器实际实现了这些机制中的哪一个(如果有),因此 MUST 只发送它们
   认为可以安全重放的 early data。

   除了重放的直接影响之外,还存在一类攻击,其中即使通常被认为是幂等的
   操作,也可能被大量重放利用(定时攻击、资源限制耗尽以及其他攻击,
   如附录 E.5所述)。可通过确保每个 0-RTT 载荷只能被重放有限次数
   来缓解这些攻击。服务器 MUST 确保它的任何实例(无论是机器、线程,还是
   相关服务基础设施内的任何其他实体)对同一 0-RTT 握手最多接受一次
   0-RTT;这会将重放次数限制为部署中的服务器实例数量。这种保证可以
   通过本地记录最近收到的 ClientHello 数据并拒绝重复来完成,或通过任何




Rescorla                     标准化进程                      [第 98 页]


RFC 8446                           TLS                       2018 年 8 月


   提供相同或更强保证的其他方法完成。“每个服务器实例最多一次”的保证
   是最低要求;在可行时,服务器 SHOULD 进一步限制 0-RTT 重放。

   第二类攻击无法在 TLS 层防止,MUST 由任何应用来处理。注意,任何其
   客户端实现任意类型重试行为的应用,都已经需要实现某种反重放防御。

8.1.  一次性票据

   最简单的反重放防御形式是服务器只允许每个会话票据使用一次。例如,
   服务器可以维护所有未决有效票据的数据库,在每个票据被使用时从数据库
   中删除。如果提供了未知票据,则服务器会回退到完整握手。

   如果票据不是自包含的,而是数据库键,并且对应的 PSK 在使用时被删除,
   则使用 PSK 建立的连接享有前向保密性。当 PSK 在没有 (EC)DHE 的情况下
   使用时,这会提升所有 0-RTT 数据和 PSK 使用的安全性。

   因为此机制要求在具有多个分布式服务器的环境中在服务器节点之间共享
   会话数据库,所以与自加密票据相比,可能难以实现较高比例的成功 PSK
   0-RTT 连接。与会话数据库不同,即使没有一致存储,会话票据也可以成功
   执行基于 PSK 的会话建立;不过,当允许 0-RTT 时,它们仍需要一致存储
   来对 0-RTT 数据执行反重放,如下一节所详述。

8.2.  ClientHello 记录

   另一种反重放形式是记录从 ClientHello 派生出的唯一值(通常是随机值
   或 PSK binder),并拒绝重复项。记录所有 ClientHello 会导致状态无界
   增长,但服务器可以改为记录给定时间窗口内的 ClientHello,并使用
   “obfuscated_ticket_age”确保票据不会在该窗口之外被重用。

   为了实现这一点,当收到 ClientHello 时,服务器首先按第 4.2.11 节
   所述验证 PSK binder。然后,它按下一节所述计算 expected_arrival_time,
   如果该时间在记录窗口之外,则拒绝 0-RTT,并回退到 1-RTT 握手。





Rescorla                     标准化进程                      [第 99 页]


RFC 8446                           TLS                       2018 年 8 月


   如果 expected_arrival_time 在窗口内,则服务器检查是否已记录匹配的
   ClientHello。如果找到一个,则它要么使用“illegal_parameter”告警中止
   握手,要么接受 PSK 但拒绝 0-RTT。如果未找到匹配的 ClientHello,
   则它接受 0-RTT,然后在 expected_arrival_time 位于窗口内的期间存储
   该 ClientHello。服务器 MAY 还实现带有误报的数据存储,例如 Bloom
   过滤器;在这种情况下,它们 MUST 通过拒绝 0-RTT 来响应表面上的重放,
   但 MUST NOT 中止握手。

   服务器 MUST 只从 ClientHello 的已验证部分派生存储键。如果 ClientHello
   包含多个 PSK identity,则攻击者可以为较低偏好的 identity 创建具有
   不同 binder 值的多个 ClientHello,假设服务器不会验证它(如
   第 4.2.11 节所建议)。也就是说,如果客户端发送 PSK A 和 B,但
   服务器偏好 A,则攻击者可以更改 B 的 binder,而不影响 A 的 binder。
   如果 B 的 binder 是存储键的一部分,则此 ClientHello 不会显示为重复,
   这将导致 ClientHello 被接受,并可能导致重放缓存污染等副作用,尽管
   任何 0-RTT 数据都无法被解密,因为它会使用不同密钥。如果使用已验证的
   binder 或 ClientHello.random 作为存储键,则此攻击不可能发生。

   因为此机制不要求存储所有未决票据,所以在具有高恢复率和 0-RTT 的
   分布式系统中可能更容易实现,代价是反重放防御可能更弱,因为可靠存储
   和检索已接收的 ClientHello 消息存在困难。在许多这样的系统中,对所有
   已接收 ClientHello 进行全局一致存储并不实际。在这种情况下,最佳反
   重放保护是让单个存储区域对给定票据具有权威性,并在任何其他区域拒绝
   该票据的 0-RTT。此方法防止攻击者进行简单重放,因为只有一个区域会
   接受 0-RTT 数据。较弱的设计是为每个区域实现单独存储,但允许在任何
   区域使用 0-RTT。此方法将重放次数限制为每个区域一次。当然,无论哪种
   设计,应用消息重复仍然可能发生。

   当实现刚启动时,只要其记录窗口的任何部分与启动时间重叠,它们 SHOULD
   拒绝 0-RTT。否则,它们会面临接受最初在该期间发送的重放的风险。







Rescorla                     标准化进程                     [第 100 页]


RFC 8446                           TLS                       2018 年 8 月


   注意:如果客户端时钟比服务器时钟快得多,则可能收到一个在未来窗口
   之外的 ClientHello,在这种情况下,它可能被 1-RTT 接受,导致客户端
   重试,然后稍后又可被 0-RTT 接受。这是第 8 节中描述的第二种
   攻击形式的另一个变体。

8.3.  新鲜性检查

   因为 ClientHello 指示客户端发送它的时间,所以可以高效判断某个
   ClientHello 是否可能是在相当近期发送的,并只对这样的 ClientHello
   接受 0-RTT,否则回退到 1-RTT 握手。对于第 8.2 节中描述的
   ClientHello 存储机制,这是必要的,因为否则服务器需要存储无限数量的
   ClientHello;对于自包含的一次性票据,这也是有用的优化,因为它允许
   高效拒绝不能用于 0-RTT 的 ClientHello。

   为了实现此机制,服务器需要存储服务器生成会话票据的时间,并用客户端
   与服务器之间往返时间的估计值进行偏移。即:

       adjusted_creation_time = creation_time + estimated_RTT

   此值可以编码在票据中,从而避免需要为每个未决票据保持状态。服务器
   可以通过从客户端“pre_shared_key”扩展中的“obfuscated_ticket_age”
   参数中减去票据的“ticket_age_add”值,确定客户端对票据年龄的看法。
   服务器可以按如下方式确定 ClientHello 的 expected_arrival_time:

     expected_arrival_time = adjusted_creation_time + clients_ticket_age

   收到新的 ClientHello 时,会将 expected_arrival_time 与当前服务器
   挂钟时间比较;如果它们相差超过某个数值,则拒绝 0-RTT,但可以允许
   1-RTT 握手完成。














Rescorla                     标准化进程                     [第 101 页]


RFC 8446                           TLS                       2018 年 8 月


   可能有若干误差来源导致 expected_arrival_time 与测量时间不匹配。
   客户端和服务器时钟速率的变化可能很小,尽管绝对时间可能相差很大。
   网络传播延迟最可能导致合法的经过时间值出现不匹配。NewSessionTicket
   和 ClientHello 消息都可能被重传并因此延迟,这可能被 TCP 隐藏。对于
   互联网客户端,这意味着需要约十秒量级的窗口来计入时钟误差和测量变化;
   其他部署场景可能有不同需求。时钟偏斜分布并不对称,因此最优折中可能
   涉及允许不匹配值的非对称范围。

   注意,仅靠新鲜性检查不足以防止重放,因为它无法在误差窗口期间检测
   重放;根据带宽和系统容量,这个窗口在真实场景中可能包含数十亿次重放。
   此外,此新鲜性检查只在收到 ClientHello 时执行,而不是在收到后续 early
   Application Data 记录时执行。early data 被接受后,记录可能会在更长
   时间内继续流式传输到服务器。

9.  合规要求

9.1.  强制实现的密码套件

   在没有应用配置文件标准另有规定的情况下:

   符合 TLS 的应用 MUST 实现 TLS_AES_128_GCM_SHA256 [GCM] 密码套件,
   并 SHOULD 实现 TLS_AES_256_GCM_SHA384 [GCM] 和
   TLS_CHACHA20_POLY1305_SHA256 [RFC8439] 密码套件(见
   附录 B.4)。

   符合 TLS 的应用 MUST 支持使用 rsa_pkcs1_sha256(用于证书)、
   rsa_pss_rsae_sha256(用于 CertificateVerify 和证书)以及
   ecdsa_secp256r1_sha256 的数字签名。符合 TLS 的应用 MUST 支持使用
   secp256r1(NIST P-256)的密钥交换,并 SHOULD 支持使用 X25519
   [RFC7748] 的密钥交换。











Rescorla                     标准化进程                     [第 102 页]


RFC 8446                           TLS                       2018 年 8 月


9.2.  强制实现的扩展

   在没有应用配置文件标准另有规定的情况下,符合 TLS 的应用 MUST 实现
   以下 TLS 扩展:

   -  Supported Versions(“supported_versions”;第 4.2.1 节)

   -  Cookie(“cookie”;第 4.2.2 节)

   -  Signature Algorithms(“signature_algorithms”;第 4.2.3 节)

   -  Signature Algorithms Certificate(“signature_algorithms_cert”;
      第 4.2.3 节)

   -  Negotiated Groups(“supported_groups”;第 4.2.7 节)

   -  Key Share(“key_share”;第 4.2.8 节)

   -  Server Name Indication(“server_name”;[RFC6066] 第 3 节)

   所有实现 MUST 在提供适用特性时发送并使用这些扩展:

   -  “supported_versions”对于所有 ClientHello、ServerHello 和
      HelloRetryRequest 消息都是 REQUIRED。

   -  “signature_algorithms”对于证书认证是 REQUIRED。

   -  “supported_groups”对于使用 DHE 或 ECDHE 密钥交换的 ClientHello
      消息是 REQUIRED。

   -  “key_share”对于 DHE 或 ECDHE 密钥交换是 REQUIRED。

   -  “pre_shared_key”对于 PSK 密钥协定是 REQUIRED。

   -  “psk_key_exchange_modes”对于 PSK 密钥协定是 REQUIRED。














Rescorla                     标准化进程                     [第 103 页]


RFC 8446                           TLS                       2018 年 8 月


   如果 ClientHello 包含一个主体中含有 0x0304 的“supported_versions”
   扩展,则认为客户端正尝试使用本规范进行协商。这样的 ClientHello
   消息 MUST 满足以下要求:

   -  如果不包含“pre_shared_key”扩展,则它 MUST 同时包含
      “signature_algorithms”扩展和“supported_groups”扩展。

   -  如果包含“supported_groups”扩展,则它 MUST 也包含“key_share”
      扩展,反之亦然。允许空的 KeyShare.client_shares 向量。

   收到不符合这些要求的 ClientHello 的服务器 MUST 使用
   “missing_extension”告警中止握手。

   此外,所有实现 MUST 支持在能够使用“server_name”扩展的应用中使用
   该扩展。服务器 MAY 要求客户端发送有效的“server_name”扩展。要求此
   扩展的服务器 SHOULD 通过使用“missing_extension”告警终止连接来响应
   缺少“server_name”扩展的 ClientHello。

9.3.  协议不变量

   本节描述 TLS 端点和中间盒 MUST 遵循的不变量。它也适用于 TLS 的
   早期版本。

   TLS 被设计为可以安全且兼容地扩展。较新的客户端或服务器在与较新的
   对等方通信时,应协商最偏好的共同参数。TLS 握手提供降级保护:在较新
   客户端与较新服务器之间传递流量而不终止 TLS 的中间盒,应无法影响握手
   (见附录 E.1)。同时,部署会以不同速度更新,因此较新的客户端
   或服务器 MAY 继续支持较旧参数,这会允许它与较旧端点互操作。













Rescorla                     标准化进程                     [第 104 页]


RFC 8446                           TLS                       2018 年 8 月


   为了使这一点可行,实现 MUST 正确处理可扩展字段:

   -  发送 ClientHello 的客户端 MUST 支持其中通告的所有参数。否则,
      服务器可能通过选择其中一个参数而无法互操作。

   -  收到 ClientHello 的服务器 MUST 正确忽略所有未识别的密码套件、
      扩展和其他参数。否则,它可能无法与较新的客户端互操作。在
      TLS 1.3 中,收到 CertificateRequest 或 NewSessionTicket 的客户端
      MUST 也忽略所有未识别的扩展。

   -  终止 TLS 连接的中间盒 MUST 表现为符合规范的 TLS 服务器(面向原始
      客户端),包括拥有客户端愿意接受的证书;同时也表现为符合规范的
      TLS 客户端(面向原始服务器),包括验证原始服务器的证书。特别是,
      它 MUST 生成自己的 ClientHello,只包含它理解的参数,并且 MUST 生成
      新的 ServerHello 随机值,而不是转发端点的值。

      注意,TLS 的协议要求和安全分析只分别适用于这两个连接。安全部署
      TLS 终结器需要额外的安全考虑,这超出本文档范围。

   -  转发其不理解的 ClientHello 参数的中间盒 MUST NOT 处理该 ClientHello
      之后的任何消息。它 MUST 不加修改地转发所有后续流量。否则,它可能
      无法与较新的客户端和服务器互操作。

      被转发的 ClientHello 可能包含中间盒不支持的特性通告,因此响应中
      可能包含中间盒不识别的未来 TLS 新增内容。这些新增内容 MAY 任意
      更改 ClientHello 之后的任何消息。特别是,ServerHello 中发送的值
      可能改变,ServerHello 格式可能改变,TLSCiphertext 格式也可能改变。

   TLS 1.3 的设计受到广泛部署的非合规 TLS 中间盒约束(见
   附录 D.4);然而,它并未放宽这些不变量。这些中间盒仍然是
   非合规的。







Rescorla                     标准化进程                     [第 105 页]


RFC 8446                           TLS                       2018 年 8 月


10.  安全考虑

   本备忘录全文都讨论了安全问题,尤其是在附录 C、D 和 E 中。

11.  IANA 考虑

   本文档使用了若干最初在 [RFC4346] 中创建并在 [RFC8447] 中更新的注册表。
   IANA 已更新这些注册表以引用本文档。注册表及其分配策略如下:

   -  TLS Cipher Suites 注册表:第一字节在 0-254(十进制)范围内的值
      通过 Specification Required [RFC8126] 分配。第一字节为
      255(十进制)的值保留用于 Private Use [RFC8126]。

      IANA 已将附录 B.4中列出的密码套件添加到该注册表。“Value”
      和“Description”列取自表中。“DTLS-OK”和“Recommended”列对每个
      新密码套件均标记为“Y”。

   -  TLS ContentType 注册表:未来值通过 Standards Action [RFC8126]
      分配。

   -  TLS Alerts 注册表:未来值通过 Standards Action [RFC8126] 分配。
      IANA 已用附录 B.2中的值填充此注册表。所有这些值的“DTLS-OK”
      列均标记为“Y”。标记为“_RESERVED”的值带有描述其先前用法的注释。

   -  TLS HandshakeType 注册表:未来值通过 Standards Action [RFC8126]
      分配。IANA 已更新此注册表,将项目 4 从“NewSessionTicket”重命名为
      “new_session_ticket”,并用附录 B.3中的值填充此注册表。
      所有这些值的“DTLS-OK”列均标记为“Y”。标记为“_RESERVED”的值带有
      描述其先前或临时用法的注释。













Rescorla                     标准化进程                     [第 106 页]


RFC 8446                           TLS                       2018 年 8 月


   本文档还使用了最初在 [RFC4366] 中创建的 TLS ExtensionType Values
   注册表。IANA 已更新它以引用本文档。注册表变更如下:

   -  IANA 已按如下方式更新注册策略:

      第一字节在 0-254(十进制)范围内的值通过 Specification Required
      [RFC8126] 分配。第一字节为 255(十进制)的值保留用于
      Private Use [RFC8126]。

   -  IANA 已更新此注册表,以包含“key_share”、“pre_shared_key”、
      “psk_key_exchange_modes”、“early_data”、“cookie”、“supported_versions”、
      “certificate_authorities”、“oid_filters”、“post_handshake_auth”和
      “signature_algorithms_cert”扩展,其值为本文档中定义的值,并且
      “Recommended”值为“Y”。

   -  IANA 已更新此注册表,以包含一个“TLS 1.3”列,列出该扩展可以出现
      的消息。此列已最初用第 4.2 节中的表填充,任何未列在其中的
      扩展标记为“-”,表示它不由 TLS 1.3 使用。

   本文档更新了 TLS Certificate Types 注册表中的一个条目,该注册表最初
   在 [RFC6091] 中创建,并在 [RFC8447] 中更新。IANA 已更新值 1 的条目,
   使其名称为“OpenPGP_RESERVED”,“Recommended”值为“N”,注释为
   “Used in TLS versions prior to 1.3.”

   本文档更新了 TLS Certificate Status Types 注册表中的一个条目,该注册表
   最初在 [RFC6961] 中创建。IANA 已更新值 2 的条目,使其名称为
   “ocsp_multi_RESERVED”,注释为“Used in TLS versions prior to 1.3”。

   本文档更新了 TLS Supported Groups 注册表中的两个条目(该注册表由
   [RFC4492] 以不同名称创建;现在由 [RFC8422] 维护),并由 [RFC7919]
   和 [RFC8447] 更新。值 29 和 30(x25519 和 x448)的条目已更新为也引用
   本文档。












Rescorla                     标准化进程                     [第 107 页]


RFC 8446                           TLS                       2018 年 8 月


   此外,本文档定义了两个由 IANA 维护的新注册表:

   -  TLS SignatureScheme 注册表:第一字节在 0-253(十进制)范围内的
      值通过 Specification Required [RFC8126] 分配。第一字节为
      254 或 255(十进制)的值保留用于 Private Use [RFC8126]。
      第一字节在 0-6 范围内,或第二字节在 0-3 范围内且当前未分配的值,
      保留用于向后兼容。此注册表有一个“Recommended”列。该注册表已
      初始填充第 4.2.3 节中描述的值。以下值标记为“Recommended”:
      ecdsa_secp256r1_sha256、ecdsa_secp384r1_sha384、
      rsa_pss_rsae_sha256、rsa_pss_rsae_sha384、rsa_pss_rsae_sha512、
      rsa_pss_pss_sha256、rsa_pss_pss_sha384、rsa_pss_pss_sha512 和
      ed25519。除非明确请求,否则“Recommended”列赋值为“N”;添加
      “Recommended”值为“Y”的值需要 Standards Action [RFC8126]。
      Y->N 转换 REQUIRED 需要 IESG Approval。

   -  TLS PskKeyExchangeMode 注册表:0-253(十进制)范围内的值通过
      Specification Required [RFC8126] 分配。值 254 和 255(十进制)
      保留用于 Private Use [RFC8126]。此注册表有一个“Recommended”列。
      该注册表已初始填充 psk_ke (0) 和 psk_dhe_ke (1)。二者都标记为
      “Recommended”。除非明确请求,否则“Recommended”列赋值为“N”;
      添加“Recommended”值为“Y”的值需要 Standards Action [RFC8126]。
      Y->N 转换 REQUIRED 需要 IESG Approval。





















Rescorla                     标准化进程                     [第 108 页]


RFC 8446                           TLS                       2018 年 8 月


12.  参考文献

12.1.  规范性参考文献

   [DH76]     Diffie, W. and M. Hellman, "New directions in
              cryptography", IEEE Transactions on Information
              Theory, Vol. 22 No. 6, pp. 644-654,
              DOI 10.1109/TIT.1976.1055638, November 1976.

   [ECDSA]    American National Standards Institute, "Public Key
              Cryptography for the Financial Services Industry: The
              Elliptic Curve Digital Signature Algorithm (ECDSA)",
              ANSI ANS X9.62-2005, November 2005.

   [GCM]      Dworkin, M., "Recommendation for Block Cipher Modes of
              Operation: Galois/Counter Mode (GCM) and GMAC",
              NIST Special Publication 800-38D,
              DOI 10.6028/NIST.SP.800-38D, November 2007.

   [RFC2104]  Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
              Hashing for Message Authentication", RFC 2104,
              DOI 10.17487/RFC2104, February 1997,
              <https://www.rfc-editor.org/info/rfc2104>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/info/rfc2119>.

   [RFC5116]  McGrew, D., "An Interface and Algorithms for Authenticated
              Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008,
              <https://www.rfc-editor.org/info/rfc5116>.

   [RFC5280]  Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
              Housley, R., and W. Polk, "Internet X.509 Public Key
              Infrastructure Certificate and Certificate Revocation List
              (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
              <https://www.rfc-editor.org/info/rfc5280>.

   [RFC5705]  Rescorla, E., "Keying Material Exporters for Transport
              Layer Security (TLS)", RFC 5705, DOI 10.17487/RFC5705,
              March 2010, <https://www.rfc-editor.org/info/rfc5705>.

   [RFC5756]  Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk,
              "Updates for RSAES-OAEP and RSASSA-PSS Algorithm
              Parameters", RFC 5756, DOI 10.17487/RFC5756, January 2010,
              <https://www.rfc-editor.org/info/rfc5756>.




Rescorla                     标准化进程                     [第 109 页]


RFC 8446                           TLS                       2018 年 8 月


   [RFC5869]  Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
              Key Derivation Function (HKDF)", RFC 5869,
              DOI 10.17487/RFC5869, May 2010,
              <https://www.rfc-editor.org/info/rfc5869>.

   [RFC6066]  Eastlake 3rd, D., "Transport Layer Security (TLS)
              Extensions: Extension Definitions", RFC 6066,
              DOI 10.17487/RFC6066, January 2011,
              <https://www.rfc-editor.org/info/rfc6066>.

   [RFC6655]  McGrew, D. and D. Bailey, "AES-CCM Cipher Suites for
              Transport Layer Security (TLS)", RFC 6655,
              DOI 10.17487/RFC6655, July 2012,
              <https://www.rfc-editor.org/info/rfc6655>.

   [RFC6960]  Santesson, S., Myers, M., Ankney, R., Malpani, A.,
              Galperin, S., and C. Adams, "X.509 Internet Public Key
              Infrastructure Online Certificate Status Protocol - OCSP",
              RFC 6960, DOI 10.17487/RFC6960, June 2013,
              <https://www.rfc-editor.org/info/rfc6960>.

   [RFC6961]  Pettersen, Y., "The Transport Layer Security (TLS)
              Multiple Certificate Status Request Extension", RFC 6961,
              DOI 10.17487/RFC6961, June 2013,
              <https://www.rfc-editor.org/info/rfc6961>.

   [RFC6962]  Laurie, B., Langley, A., and E. Kasper, "Certificate
              Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
              <https://www.rfc-editor.org/info/rfc6962>.

   [RFC6979]  Pornin, T., "Deterministic Usage of the Digital Signature
              Algorithm (DSA) and Elliptic Curve Digital Signature
              Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979,
              August 2013, <https://www.rfc-editor.org/info/rfc6979>.

   [RFC7301]  Friedl, S., Popov, A., Langley, A., and E. Stephan,
              "Transport Layer Security (TLS) Application-Layer Protocol
              Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301,
              July 2014, <https://www.rfc-editor.org/info/rfc7301>.

   [RFC7507]  Moeller, B. and A. Langley, "TLS Fallback Signaling Cipher
              Suite Value (SCSV) for Preventing Protocol Downgrade
              Attacks", RFC 7507, DOI 10.17487/RFC7507, April 2015,
              <https://www.rfc-editor.org/info/rfc7507>.

   [RFC7748]  Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves
              for Security", RFC 7748, DOI 10.17487/RFC7748,
              January 2016, <https://www.rfc-editor.org/info/rfc7748>.



Rescorla                     标准化进程                     [第 110 页]


RFC 8446                           TLS                       2018 年 8 月


   [RFC7919]  Gillmor, D., "Negotiated Finite Field Diffie-Hellman
              Ephemeral Parameters for Transport Layer Security (TLS)",
              RFC 7919, DOI 10.17487/RFC7919, August 2016,
              <https://www.rfc-editor.org/info/rfc7919>.

   [RFC8017]  Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch,
              "PKCS #1: RSA Cryptography Specifications Version 2.2",
              RFC 8017, DOI 10.17487/RFC8017, November 2016,
              <https://www.rfc-editor.org/info/rfc8017>.

   [RFC8032]  Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
              Signature Algorithm (EdDSA)", RFC 8032,
              DOI 10.17487/RFC8032, January 2017,
              <https://www.rfc-editor.org/info/rfc8032>.

   [RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
              Writing an IANA Considerations Section in RFCs", BCP 26,
              RFC 8126, DOI 10.17487/RFC8126, June 2017,
              <https://www.rfc-editor.org/info/rfc8126>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
              RFC 2119 Key Words", BCP 14, RFC 8174,
              DOI 10.17487/RFC8174, May 2017,
              <https://www.rfc-editor.org/info/rfc8174>.

   [RFC8439]  Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF
              Protocols", RFC 8439, DOI 10.17487/RFC8439, June 2018,
              <https://www.rfc-editor.org/info/rfc8439>.

   [SHS]      Dang, Q., "Secure Hash Standard (SHS)", National Institute
              of Standards and Technology report,
              DOI 10.6028/NIST.FIPS.180-4, August 2015.

   [X690]     ITU-T, "Information technology -- ASN.1 encoding rules:
              Specification of Basic Encoding Rules (BER), Canonical
              Encoding Rules (CER) and Distinguished Encoding Rules
              (DER)", ISO/IEC 8825-1:2015, November 2015.














Rescorla                     标准化进程                     [第 111 页]


RFC 8446                           TLS                       2018 年 8 月


12.2.  资料性参考文献

   [AEAD-LIMITS]
              Luykx, A. and K. Paterson, "Limits on Authenticated
              Encryption Use in TLS", August 2017,
              <http://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf>.

   [BBFGKZ16]
              Bhargavan, K., Brzuska, C., Fournet, C., Green, M.,
              Kohlweiss, M., and S. Zanella-Beguelin, "Downgrade
              Resilience in Key-Exchange Protocols", Proceedings of IEEE
              Symposium on Security and Privacy (San Jose),
              DOI 10.1109/SP.2016.37, May 2016.

   [BBK17]    Bhargavan, K., Blanchet, B., and N. Kobeissi, "Verified
              Models and Reference Implementations for the TLS 1.3
              Standard Candidate", Proceedings of IEEE Symposium on
              Security and Privacy (San Jose), DOI 10.1109/SP.2017.26,
              May 2017.

   [BDFKPPRSZZ16]
              Bhargavan, K., Delignat-Lavaud, A., Fournet, C.,
              Kohlweiss, M., Pan, J., Protzenko, J., Rastogi, A., Swamy,
              N., Zanella-Beguelin, S., and J. Zinzindohoue,
              "Implementing and Proving the TLS 1.3 Record Layer",
              Proceedings of IEEE Symposium on Security and Privacy (San
              Jose), May 2017, <https://eprint.iacr.org/2016/1178>.

   [Ben17a]   Benjamin, D., "Presentation before the TLS WG at
              IETF 100", November 2017,
              <https://datatracker.ietf.org/meeting/100/materials/
              slides-100-tls-sessa-tls13/>.

   [Ben17b]   Benjamin, D., "Additional TLS 1.3 results from Chrome",
              message to the TLS mailing list, 18 December 2017,
              <https://www.ietf.org/mail-archive/web/tls/current/
              msg25168.html>.

   [Blei98]   Bleichenbacher, D., "Chosen Ciphertext Attacks against
              Protocols Based on RSA Encryption Standard PKCS #1",
              Proceedings of CRYPTO '98, 1998.

   [BMMRT15]  Badertscher, C., Matt, C., Maurer, U., Rogaway, P., and B.
              Tackmann, "Augmented Secure Channels and the Goal of the
              TLS 1.3 Record Layer", ProvSec 2015, September 2015,
              <https://eprint.iacr.org/2015/394>.





Rescorla                     标准化进程                     [第 112 页]


RFC 8446                           TLS                       2018 年 8 月


   [BT16]     Bellare, M. and B. Tackmann, "The Multi-User Security of
              Authenticated Encryption: AES-GCM in TLS 1.3", Proceedings
              of CRYPTO 2016, July 2016,
              <https://eprint.iacr.org/2016/564>.

   [CCG16]    Cohn-Gordon, K., Cremers, C., and L. Garratt, "On
              Post-compromise Security", IEEE Computer Security
              Foundations Symposium, DOI 10.1109/CSF.2016.19, July 2015.

   [CHECKOWAY]
              Checkoway, S., Maskiewicz, J., Garman, C., Fried, J.,
              Cohney, S., Green, M., Heninger, N., Weinmann, R.,
              Rescorla, E., and H. Shacham, "A Systematic Analysis of
              the Juniper Dual EC Incident", Proceedings of the 2016 ACM
              SIGSAC Conference on Computer and Communications Security
              - CCS '16, DOI 10.1145/2976749.2978395, October 2016.

   [CHHSV17]  Cremers, C., Horvat, M., Hoyland, J., Scott, S., and T.
              van der Merwe, "Awkward Handshake: Possible mismatch of
              client/server view on client authentication in
              post-handshake mode in Revision 18", message to the TLS
              mailing list, 10 February 2017, <https://www.ietf.org/
              mail-archive/web/tls/current/msg22382.html>.

   [CHSV16]   Cremers, C., Horvat, M., Scott, S., and T. van der Merwe,
              "Automated Analysis and Verification of TLS 1.3: 0-RTT,
              Resumption and Delayed Authentication", Proceedings of
              IEEE Symposium on Security and Privacy (San Jose),
              DOI 10.1109/SP.2016.35, May 2016,
              <https://ieeexplore.ieee.org/document/7546518/>.

   [CK01]     Canetti, R. and H. Krawczyk, "Analysis of Key-Exchange
              Protocols and Their Use for Building Secure Channels",
              Proceedings of Eurocrypt 2001,
              DOI 10.1007/3-540-44987-6_28, April 2001.

   [CLINIC]   Miller, B., Huang, L., Joseph, A., and J. Tygar, "I Know
              Why You Went to the Clinic: Risks and Realization of HTTPS
              Traffic Analysis", Privacy Enhancing Technologies, pp.
              143-163, DOI 10.1007/978-3-319-08506-7_8, 2014.

   [DFGS15]   Dowling, B., Fischlin, M., Guenther, F., and D. Stebila,
              "A Cryptographic Analysis of the TLS 1.3 Handshake
              Protocol Candidates", Proceedings of ACM CCS 2015,
              October 2015, <https://eprint.iacr.org/2015/914>.






Rescorla                     标准化进程                     [第 113 页]


RFC 8446                           TLS                       2018 年 8 月


   [DFGS16]   Dowling, B., Fischlin, M., Guenther, F., and D. Stebila,
              "A Cryptographic Analysis of the TLS 1.3 Full and
              Pre-shared Key Handshake Protocol", TRON 2016,
              February 2016, <https://eprint.iacr.org/2016/081>.

   [DOW92]    Diffie, W., van Oorschot, P., and M. Wiener,
              "Authentication and authenticated key exchanges", Designs,
              Codes and Cryptography, DOI 10.1007/BF00124891, June 1992.

   [DSS]      National Institute of Standards and Technology, U.S.
              Department of Commerce, "Digital Signature Standard
              (DSS)", NIST FIPS PUB 186-4, DOI 10.6028/NIST.FIPS.186-4,
              July 2013.

   [FG17]     Fischlin, M. and F. Guenther, "Replay Attacks on Zero
              Round-Trip Time: The Case of the TLS 1.3 Handshake
              Candidates", Proceedings of EuroS&P 2017, April 2017,
              <https://eprint.iacr.org/2017/082>.

   [FGSW16]   Fischlin, M., Guenther, F., Schmidt, B., and B. Warinschi,
              "Key Confirmation in Key Exchange: A Formal Treatment and
              Implications for TLS 1.3", Proceedings of IEEE Symposium
              on Security and Privacy (San Jose),
              DOI 10.1109/SP.2016.34, May 2016,
              <https://ieeexplore.ieee.org/document/7546517/>.

   [FW15]     Weimer, F., "Factoring RSA Keys With TLS Perfect Forward
              Secrecy", September 2015.

   [HCJC16]   Husak, M., Cermak, M., Jirsik, T., and P. Celeda, "HTTPS
              traffic analysis and client identification using passive
              SSL/TLS fingerprinting", EURASIP Journal on Information
              Security, Vol. 2016, DOI 10.1186/s13635-016-0030-7,
              February 2016.

   [HGFS15]   Hlauschek, C., Gruber, M., Fankhauser, F., and C. Schanes,
              "Prying Open Pandora's Box: KCI Attacks against TLS",
              Proceedings of USENIX Workshop on Offensive Technologies,
              August 2015.

   [IEEE1363]
              IEEE, "IEEE Standard Specifications for Public Key
              Cryptography", IEEE Std. 1363-2000,
              DOI 10.1109/IEEESTD.2000.92292.







Rescorla                     标准化进程                     [第 114 页]


RFC 8446                           TLS                       2018 年 8 月


   [JSS15]    Jager, T., Schwenk, J., and J. Somorovsky, "On the
              Security of TLS 1.3 and QUIC Against Weaknesses in PKCS#1
              v1.5 Encryption", Proceedings of ACM CCS 2015,
              DOI 10.1145/2810103.2813657, October 2015,
              <https://www.nds.rub.de/media/nds/
              veroeffentlichungen/2015/08/21/Tls13QuicAttacks.pdf>.

   [KEYAGREEMENT]
              Barker, E., Chen, L., Roginsky, A., Vassilev, A., and R.
              Davis, "Recommendation for Pair-Wise Key Establishment
              Schemes Using Discrete Logarithm Cryptography", National
              Institute of Standards and Technology,
              DOI 10.6028/NIST.SP.800-56Ar3, April 2018.

   [Kraw10]   Krawczyk, H., "Cryptographic Extraction and Key
              Derivation: The HKDF Scheme", Proceedings of CRYPTO 2010,
              August 2010, <https://eprint.iacr.org/2010/264>.

   [Kraw16]   Krawczyk, H., "A Unilateral-to-Mutual Authentication
              Compiler for Key Exchange (with Applications to Client
              Authentication in TLS 1.3", Proceedings of ACM CCS 2016,
              October 2016, <https://eprint.iacr.org/2016/711>.

   [KW16]     Krawczyk, H. and H. Wee, "The OPTLS Protocol and TLS 1.3",
              Proceedings of EuroS&P 2016, March 2016,
              <https://eprint.iacr.org/2015/978>.

   [LXZFH16]  Li, X., Xu, J., Zhang, Z., Feng, D., and H. Hu, "Multiple
              Handshakes Security of TLS 1.3 Candidates", Proceedings of
              IEEE Symposium on Security and Privacy (San Jose),
              DOI 10.1109/SP.2016.36, May 2016,
              <https://ieeexplore.ieee.org/document/7546519/>.

   [Mac17]    MacCarthaigh, C., "Security Review of TLS1.3 0-RTT",
              March 2017, <https://github.com/tlswg/tls13-spec/
              issues/1001>.

   [PS18]     Patton, C. and T. Shrimpton, "Partially specified
              channels: The TLS 1.3 record layer without elision", 2018,
              <https://eprint.iacr.org/2018/634>.

   [PSK-FINISHED]
              Scott, S., Cremers, C., Horvat, M., and T. van der Merwe,
              "Revision 10: possible attack if client authentication is
              allowed during PSK", message to the TLS mailing list,
              31 October 2015, <https://www.ietf.org/
              mail-archive/web/tls/current/msg18215.html>.




Rescorla                     标准化进程                     [第 115 页]


RFC 8446                           TLS                       2018 年 8 月


   [REKEY]    Abdalla, M. and M. Bellare, "Increasing the Lifetime of a
              Key: A Comparative Analysis of the Security of Re-keying
              Techniques", ASIACRYPT 2000, DOI 10.1007/3-540-44448-3_42,
              October 2000.

   [Res17a]   Rescorla, E., "Preliminary data on Firefox TLS 1.3
              Middlebox experiment", message to the TLS mailing list,
              5 December 2017, <https://www.ietf.org/
              mail-archive/web/tls/current/msg25091.html>.

   [Res17b]   Rescorla, E., "More compatibility measurement results",
              message to the TLS mailing list, 22 December 2017,
              <https://www.ietf.org/mail-archive/web/tls/current/
              msg25179.html>.

   [RFC3552]  Rescorla, E. and B. Korver, "Guidelines for Writing RFC
              Text on Security Considerations", BCP 72, RFC 3552,
              DOI 10.17487/RFC3552, July 2003,
              <https://www.rfc-editor.org/info/rfc3552>.

   [RFC4086]  Eastlake 3rd, D., Schiller, J., and S. Crocker,
              "Randomness Requirements for Security", BCP 106, RFC 4086,
              DOI 10.17487/RFC4086, June 2005,
              <https://www.rfc-editor.org/info/rfc4086>.

   [RFC4346]  Dierks, T. and E. Rescorla, "The Transport Layer Security
              (TLS) Protocol Version 1.1", RFC 4346,
              DOI 10.17487/RFC4346, April 2006,
              <https://www.rfc-editor.org/info/rfc4346>.

   [RFC4366]  Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J.,
              and T. Wright, "Transport Layer Security (TLS)
              Extensions", RFC 4366, DOI 10.17487/RFC4366, April 2006,
              <https://www.rfc-editor.org/info/rfc4366>.

   [RFC4492]  Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B.
              Moeller, "Elliptic Curve Cryptography (ECC) Cipher Suites
              for Transport Layer Security (TLS)", RFC 4492,
              DOI 10.17487/RFC4492, May 2006,
              <https://www.rfc-editor.org/info/rfc4492>.

   [RFC5077]  Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig,
              "Transport Layer Security (TLS) Session Resumption without
              Server-Side State", RFC 5077, DOI 10.17487/RFC5077,
              January 2008, <https://www.rfc-editor.org/info/rfc5077>.






Rescorla                     标准化进程                     [第 116 页]


RFC 8446                           TLS                       2018 年 8 月


   [RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
              (TLS) Protocol Version 1.2", RFC 5246,
              DOI 10.17487/RFC5246, August 2008,
              <https://www.rfc-editor.org/info/rfc5246>.

   [RFC5764]  McGrew, D. and E. Rescorla, "Datagram Transport Layer
              Security (DTLS) Extension to Establish Keys for the Secure
              Real-time Transport Protocol (SRTP)", RFC 5764,
              DOI 10.17487/RFC5764, May 2010,
              <https://www.rfc-editor.org/info/rfc5764>.

   [RFC5929]  Altman, J., Williams, N., and L. Zhu, "Channel Bindings
              for TLS", RFC 5929, DOI 10.17487/RFC5929, July 2010,
              <https://www.rfc-editor.org/info/rfc5929>.

   [RFC6091]  Mavrogiannopoulos, N. and D. Gillmor, "Using OpenPGP Keys
              for Transport Layer Security (TLS) Authentication",
              RFC 6091, DOI 10.17487/RFC6091, February 2011,
              <https://www.rfc-editor.org/info/rfc6091>.

   [RFC6101]  Freier, A., Karlton, P., and P. Kocher, "The Secure
              Sockets Layer (SSL) Protocol Version 3.0", RFC 6101,
              DOI 10.17487/RFC6101, August 2011,
              <https://www.rfc-editor.org/info/rfc6101>.

   [RFC6176]  Turner, S. and T. Polk, "Prohibiting Secure Sockets Layer
              (SSL) Version 2.0", RFC 6176, DOI 10.17487/RFC6176,
              March 2011, <https://www.rfc-editor.org/info/rfc6176>.

   [RFC6347]  Rescorla, E. and N. Modadugu, "Datagram Transport Layer
              Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347,
              January 2012, <https://www.rfc-editor.org/info/rfc6347>.

   [RFC6520]  Seggelmann, R., Tuexen, M., and M. Williams, "Transport
              Layer Security (TLS) and Datagram Transport Layer Security
              (DTLS) Heartbeat Extension", RFC 6520,
              DOI 10.17487/RFC6520, February 2012,
              <https://www.rfc-editor.org/info/rfc6520>.

   [RFC7230]  Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
              Protocol (HTTP/1.1): Message Syntax and Routing",
              RFC 7230, DOI 10.17487/RFC7230, June 2014,
              <https://www.rfc-editor.org/info/rfc7230>.








Rescorla                     标准化进程                     [第 117 页]


RFC 8446                           TLS                       2018 年 8 月


   [RFC7250]  Wouters, P., Ed., Tschofenig, H., Ed., Gilmore, J.,
              Weiler, S., and T. Kivinen, "Using Raw Public Keys in
              Transport Layer Security (TLS) and Datagram Transport
              Layer Security (DTLS)", RFC 7250, DOI 10.17487/RFC7250,
              June 2014, <https://www.rfc-editor.org/info/rfc7250>.

   [RFC7465]  Popov, A., "Prohibiting RC4 Cipher Suites", RFC 7465,
              DOI 10.17487/RFC7465, February 2015,
              <https://www.rfc-editor.org/info/rfc7465>.

   [RFC7568]  Barnes, R., Thomson, M., Pironti, A., and A. Langley,
              "Deprecating Secure Sockets Layer Version 3.0", RFC 7568,
              DOI 10.17487/RFC7568, June 2015,
              <https://www.rfc-editor.org/info/rfc7568>.

   [RFC7627]  Bhargavan, K., Ed., Delignat-Lavaud, A., Pironti, A.,
              Langley, A., and M. Ray, "Transport Layer Security (TLS)
              Session Hash and Extended Master Secret Extension",
              RFC 7627, DOI 10.17487/RFC7627, September 2015,
              <https://www.rfc-editor.org/info/rfc7627>.

   [RFC7685]  Langley, A., "A Transport Layer Security (TLS) ClientHello
              Padding Extension", RFC 7685, DOI 10.17487/RFC7685,
              October 2015, <https://www.rfc-editor.org/info/rfc7685>.

   [RFC7924]  Santesson, S. and H. Tschofenig, "Transport Layer Security
              (TLS) Cached Information Extension", RFC 7924,
              DOI 10.17487/RFC7924, July 2016,
              <https://www.rfc-editor.org/info/rfc7924>.

   [RFC8305]  Schinazi, D. and T. Pauly, "Happy Eyeballs Version 2:
              Better Connectivity Using Concurrency", RFC 8305,
              DOI 10.17487/RFC8305, December 2017,
              <https://www.rfc-editor.org/info/rfc8305>.

   [RFC8422]  Nir, Y., Josefsson, S., and M. Pegourie-Gonnard, "Elliptic
              Curve Cryptography (ECC) Cipher Suites for Transport Layer
              Security (TLS) Versions 1.2 and Earlier", RFC 8422,
              DOI 10.17487/RFC8422, August 2018,
              <https://www.rfc-editor.org/info/rfc8422>.

   [RFC8447]  Salowey, J. and S. Turner, "IANA Registry Updates for TLS
              and DTLS", RFC 8447, DOI 10.17487/RFC8447, August 2018,
              <https://www.rfc-editor.org/info/rfc8447>.

   [RFC8449]  Thomson, M., "Record Size Limit Extension for TLS",
              RFC 8449, DOI 10.17487/RFC8449, August 2018,
              <https://www.rfc-editor.org/info/rfc8449>.



Rescorla                     标准化进程                     [第 118 页]


RFC 8446                           TLS                       2018 年 8 月


   [RSA]      Rivest, R., Shamir, A., and L. Adleman, "A Method for
              Obtaining Digital Signatures and Public-Key
              Cryptosystems", Communications of the ACM, Vol. 21 No. 2,
              pp. 120-126, DOI 10.1145/359340.359342, February 1978.

   [SIGMA]    Krawczyk, H., "SIGMA: The 'SIGn-and-MAc' Approach to
              Authenticated Diffie-Hellman and its Use in the IKE
              Protocols", Proceedings of CRYPTO 2003,
              DOI 10.1007/978-3-540-45146-4_24, August 2003.

   [SLOTH]    Bhargavan, K. and G. Leurent, "Transcript Collision
              Attacks: Breaking Authentication in TLS, IKE, and SSH",
              Network and Distributed System Security
              Symposium (NDSS 2016), DOI 10.14722/ndss.2016.23418,
              February 2016.

   [SSL2]     Hickman, K., "The SSL Protocol", February 1995.

   [TIMING]   Boneh, D. and D. Brumley, "Remote Timing Attacks Are
              Practical", USENIX Security Symposium, August 2003.

   [TLS13-TRACES]
              Thomson, M., "Example Handshake Traces for TLS 1.3", Work
              in Progress, draft-ietf-tls-tls13-vectors-06, July 2018.

   [X501]     ITU-T, "Information Technology - Open Systems
              Interconnection - The Directory: Models", ITU-T X.501,
              October 2016, <https://www.itu.int/rec/T-REC-X.501/en>.























Rescorla                     标准化进程                     [第 119 页]


RFC 8446                           TLS                       2018 年 8 月


附录 A.  状态机

   本附录提供客户端和服务器握手的合法状态转换摘要。状态名称(全大写,
   例如 START)没有正式含义,只是为了便于理解而提供。仅在特定情况下
   采取的动作以 [] 指示。记法“K_{send,recv} = foo”表示“将发送/接收
   密钥设置为给定密钥”。

A.1.  客户端

                              START <----+
               Send ClientHello |        | Recv HelloRetryRequest
          [K_send = early data] |        |
                                v        |
           /                 WAIT_SH ----+
           |                    | Recv ServerHello
           |                    | K_recv = handshake
       Can |                    V
      send |                 WAIT_EE
     early |                    | Recv EncryptedExtensions
      data |           +--------+--------+
           |     Using |                 | Using certificate
           |       PSK |                 v
           |           |            WAIT_CERT_CR
           |           |        Recv |       | Recv CertificateRequest
           |           | Certificate |       v
           |           |             |    WAIT_CERT
           |           |             |       | Recv Certificate
           |           |             v       v
           |           |              WAIT_CV
           |           |                 | Recv CertificateVerify
           |           +> WAIT_FINISHED <+
           |                  | Recv Finished
           \                  | [Send EndOfEarlyData]
                              | K_send = handshake
                              | [Send Certificate [+ CertificateVerify]]
    Can send                  | Send Finished
    app data   -->            | K_send = K_recv = application
    after here                v
                          CONNECTED

   注意,在如上所示的转换中,客户端可能以明文或使用 early data 密钥
   发送源自 ServerHello 之后消息的告警。如果客户端需要发送此类告警,
   它们 SHOULD 在可能时先重新生成密钥为握手密钥。





Rescorla                     标准化进程                     [第 120 页]


RFC 8446                           TLS                       2018 年 8 月


A.2.  服务器

                              START <-----+
               Recv ClientHello |         | Send HelloRetryRequest
                                v         |
                             RECVD_CH ----+
                                | Select parameters
                                v
                             NEGOTIATED
                                | Send ServerHello
                                | K_send = handshake
                                | Send EncryptedExtensions
                                | [Send CertificateRequest]
 Can send                       | [Send Certificate + CertificateVerify]
 app data                       | Send Finished
 after   -->                    | K_send = application
 here                  +--------+--------+
              No 0-RTT |                 | 0-RTT
                       |                 |
   K_recv = handshake  |                 | K_recv = early data
 [Skip decrypt errors] |    +------> WAIT_EOED -+
                       |    |       Recv |      | Recv EndOfEarlyData
                       |    | early data |      | K_recv = handshake
                       |    +------------+      |
                       |                        |
                       +> WAIT_FLIGHT2 <--------+
                                |
                       +--------+--------+
               No auth |                 | Client auth
                       |                 |
                       |                 v
                       |             WAIT_CERT
                       |        Recv |       | Recv Certificate
                       |       empty |       v
                       | Certificate |    WAIT_CV
                       |             |       | Recv
                       |             v       | CertificateVerify
                       +-> WAIT_FINISHED <---+
                                | Recv Finished
                                | K_recv = application
                                v
                            CONNECTED









Rescorla                     标准化进程                     [第 121 页]


RFC 8446                           TLS                       2018 年 8 月


附录 B.  协议数据结构和常量值

   本附录提供规范性协议类型和常量定义。列为“_RESERVED”的值曾用于
   TLS 的先前版本,这里为了完整性而列出。TLS 1.3 实现 MUST NOT 发送
   它们,但可能会从较旧的 TLS 实现接收到它们。

B.1.  记录层

      enum {
          invalid(0),
          change_cipher_spec(20),
          alert(21),
          handshake(22),
          application_data(23),
          heartbeat(24),  /* RFC 6520 */
          (255)
      } ContentType;

      struct {
          ContentType type;
          ProtocolVersion legacy_record_version;
          uint16 length;
          opaque fragment[TLSPlaintext.length];
      } TLSPlaintext;

      struct {
          opaque content[TLSPlaintext.length];
          ContentType type;
          uint8 zeros[length_of_padding];
      } TLSInnerPlaintext;

      struct {
          ContentType opaque_type = application_data; /* 23 */
          ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
          uint16 length;
          opaque encrypted_record[TLSCiphertext.length];
      } TLSCiphertext;












Rescorla                     标准化进程                     [第 122 页]


RFC 8446                           TLS                       2018 年 8 月


B.2.  告警消息

      enum { warning(1), fatal(2), (255) } AlertLevel;

      enum {
          close_notify(0),
          unexpected_message(10),
          bad_record_mac(20),
          decryption_failed_RESERVED(21),
          record_overflow(22),
          decompression_failure_RESERVED(30),
          handshake_failure(40),
          no_certificate_RESERVED(41),
          bad_certificate(42),
          unsupported_certificate(43),
          certificate_revoked(44),
          certificate_expired(45),
          certificate_unknown(46),
          illegal_parameter(47),
          unknown_ca(48),
          access_denied(49),
          decode_error(50),
          decrypt_error(51),
          export_restriction_RESERVED(60),
          protocol_version(70),
          insufficient_security(71),
          internal_error(80),
          inappropriate_fallback(86),
          user_canceled(90),
          no_renegotiation_RESERVED(100),
          missing_extension(109),
          unsupported_extension(110),
          certificate_unobtainable_RESERVED(111),
          unrecognized_name(112),
          bad_certificate_status_response(113),
          bad_certificate_hash_value_RESERVED(114),
          unknown_psk_identity(115),
          certificate_required(116),
          no_application_protocol(120),
          (255)
      } AlertDescription;

      struct {
          AlertLevel level;
          AlertDescription description;
      } Alert;





Rescorla                     标准化进程                     [第 123 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.  握手协议

      enum {
          hello_request_RESERVED(0),
          client_hello(1),
          server_hello(2),
          hello_verify_request_RESERVED(3),
          new_session_ticket(4),
          end_of_early_data(5),
          hello_retry_request_RESERVED(6),
          encrypted_extensions(8),
          certificate(11),
          server_key_exchange_RESERVED(12),
          certificate_request(13),
          server_hello_done_RESERVED(14),
          certificate_verify(15),
          client_key_exchange_RESERVED(16),
          finished(20),
          certificate_url_RESERVED(21),
          certificate_status_RESERVED(22),
          supplemental_data_RESERVED(23),
          key_update(24),
          message_hash(254),
          (255)
      } HandshakeType;

      struct {
          HandshakeType msg_type;    /* handshake type */
          uint24 length;             /* bytes in message */
          select (Handshake.msg_type) {
              case client_hello:          ClientHello;
              case server_hello:          ServerHello;
              case end_of_early_data:     EndOfEarlyData;
              case encrypted_extensions:  EncryptedExtensions;
              case certificate_request:   CertificateRequest;
              case certificate:           Certificate;
              case certificate_verify:    CertificateVerify;
              case finished:              Finished;
              case new_session_ticket:    NewSessionTicket;
              case key_update:            KeyUpdate;
          };
      } Handshake;









Rescorla                     标准化进程                     [第 124 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.1.  密钥交换消息

    uint16 ProtocolVersion;
    opaque Random[32];

    uint8 CipherSuite[2];    /* Cryptographic suite selector */

    struct {
        ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
        Random random;
        opaque legacy_session_id<0..32>;
        CipherSuite cipher_suites<2..2^16-2>;
        opaque legacy_compression_methods<1..2^8-1>;
        Extension extensions<8..2^16-1>;
    } ClientHello;

    struct {
        ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
        Random random;
        opaque legacy_session_id_echo<0..32>;
        CipherSuite cipher_suite;
        uint8 legacy_compression_method = 0;
        Extension extensions<6..2^16-1>;
    } ServerHello;



























Rescorla                     标准化进程                     [第 125 页]


RFC 8446                           TLS                       2018 年 8 月


    struct {
        ExtensionType extension_type;
        opaque extension_data<0..2^16-1>;
    } Extension;

    enum {
        server_name(0),                             /* RFC 6066 */
        max_fragment_length(1),                     /* RFC 6066 */
        status_request(5),                          /* RFC 6066 */
        supported_groups(10),                       /* RFC 8422, 7919 */
        signature_algorithms(13),                   /* RFC 8446 */
        use_srtp(14),                               /* RFC 5764 */
        heartbeat(15),                              /* RFC 6520 */
        application_layer_protocol_negotiation(16), /* RFC 7301 */
        signed_certificate_timestamp(18),           /* RFC 6962 */
        client_certificate_type(19),                /* RFC 7250 */
        server_certificate_type(20),                /* RFC 7250 */
        padding(21),                                /* RFC 7685 */
        RESERVED(40),                               /* Used but never
                                                       assigned */
        pre_shared_key(41),                         /* RFC 8446 */
        early_data(42),                             /* RFC 8446 */
        supported_versions(43),                     /* RFC 8446 */
        cookie(44),                                 /* RFC 8446 */
        psk_key_exchange_modes(45),                 /* RFC 8446 */
        RESERVED(46),                               /* Used but never
                                                       assigned */
        certificate_authorities(47),                /* RFC 8446 */
        oid_filters(48),                            /* RFC 8446 */
        post_handshake_auth(49),                    /* RFC 8446 */
        signature_algorithms_cert(50),              /* RFC 8446 */
        key_share(51),                              /* RFC 8446 */
        (65535)
    } ExtensionType;

    struct {
        NamedGroup group;
        opaque key_exchange<1..2^16-1>;
    } KeyShareEntry;

    struct {
        KeyShareEntry client_shares<0..2^16-1>;
    } KeyShareClientHello;

    struct {
        NamedGroup selected_group;
    } KeyShareHelloRetryRequest;




Rescorla                     标准化进程                     [第 126 页]


RFC 8446                           TLS                       2018 年 8 月


    struct {
        KeyShareEntry server_share;
    } KeyShareServerHello;

    struct {
        uint8 legacy_form = 4;
        opaque X[coordinate_length];
        opaque Y[coordinate_length];
    } UncompressedPointRepresentation;

    enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;

    struct {
        PskKeyExchangeMode ke_modes<1..255>;
    } PskKeyExchangeModes;

    struct {} Empty;

    struct {
        select (Handshake.msg_type) {
            case new_session_ticket:   uint32 max_early_data_size;
            case client_hello:         Empty;
            case encrypted_extensions: Empty;
        };
    } EarlyDataIndication;

    struct {
        opaque identity<1..2^16-1>;
        uint32 obfuscated_ticket_age;
    } PskIdentity;

    opaque PskBinderEntry<32..255>;

    struct {
        PskIdentity identities<7..2^16-1>;
        PskBinderEntry binders<33..2^16-1>;
    } OfferedPsks;

    struct {
        select (Handshake.msg_type) {
            case client_hello: OfferedPsks;
            case server_hello: uint16 selected_identity;
        };
    } PreSharedKeyExtension;







Rescorla                     标准化进程                     [第 127 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.1.1.  版本扩展

      struct {
          select (Handshake.msg_type) {
              case client_hello:
                   ProtocolVersion versions<2..254>;

              case server_hello: /* and HelloRetryRequest */
                   ProtocolVersion selected_version;
          };
      } SupportedVersions;

B.3.1.2.  Cookie 扩展

      struct {
          opaque cookie<1..2^16-1>;
      } Cookie;


































Rescorla                     标准化进程                     [第 128 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.1.3.  签名算法扩展

      enum {
          /* RSASSA-PKCS1-v1_5 algorithms */
          rsa_pkcs1_sha256(0x0401),
          rsa_pkcs1_sha384(0x0501),
          rsa_pkcs1_sha512(0x0601),

          /* ECDSA algorithms */
          ecdsa_secp256r1_sha256(0x0403),
          ecdsa_secp384r1_sha384(0x0503),
          ecdsa_secp521r1_sha512(0x0603),

          /* RSASSA-PSS algorithms with public key OID rsaEncryption */
          rsa_pss_rsae_sha256(0x0804),
          rsa_pss_rsae_sha384(0x0805),
          rsa_pss_rsae_sha512(0x0806),

          /* EdDSA algorithms */
          ed25519(0x0807),
          ed448(0x0808),

          /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
          rsa_pss_pss_sha256(0x0809),
          rsa_pss_pss_sha384(0x080a),
          rsa_pss_pss_sha512(0x080b),

          /* Legacy algorithms */
          rsa_pkcs1_sha1(0x0201),
          ecdsa_sha1(0x0203),

          /* Reserved Code Points */
          obsolete_RESERVED(0x0000..0x0200),
          dsa_sha1_RESERVED(0x0202),
          obsolete_RESERVED(0x0204..0x0400),
          dsa_sha256_RESERVED(0x0402),
          obsolete_RESERVED(0x0404..0x0500),
          dsa_sha384_RESERVED(0x0502),
          obsolete_RESERVED(0x0504..0x0600),
          dsa_sha512_RESERVED(0x0602),
          obsolete_RESERVED(0x0604..0x06FF),
          private_use(0xFE00..0xFFFF),
          (0xFFFF)
      } SignatureScheme;

      struct {
          SignatureScheme supported_signature_algorithms<2..2^16-2>;
      } SignatureSchemeList;



Rescorla                     标准化进程                     [第 129 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.1.4.  支持的组扩展

      enum {
          unallocated_RESERVED(0x0000),

          /* Elliptic Curve Groups (ECDHE) */
          obsolete_RESERVED(0x0001..0x0016),
          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
          obsolete_RESERVED(0x001A..0x001C),
          x25519(0x001D), x448(0x001E),

          /* Finite Field Groups (DHE) */
          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
          ffdhe6144(0x0103), ffdhe8192(0x0104),

          /* Reserved Code Points */
          ffdhe_private_use(0x01FC..0x01FF),
          ecdhe_private_use(0xFE00..0xFEFF),
          obsolete_RESERVED(0xFF01..0xFF02),
          (0xFFFF)
      } NamedGroup;

      struct {
          NamedGroup named_group_list<2..2^16-1>;
      } NamedGroupList;

   “obsolete_RESERVED”范围内的值用于 TLS 的先前版本,并且 MUST NOT
   由 TLS 1.3 实现提供或协商。废弃曲线存在各种已知/理论弱点,或使用
   很少,在某些情况下仅由于无意的服务器配置问题而使用。它们不再被认为
   适合一般用途,应被假定为可能不安全。这里指定的曲线集合足以与所有
   当前部署且正确配置的 TLS 实现互操作。
















Rescorla                     标准化进程                     [第 130 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.2.  服务器参数消息

      opaque DistinguishedName<1..2^16-1>;

      struct {
          DistinguishedName authorities<3..2^16-1>;
      } CertificateAuthoritiesExtension;

      struct {
          opaque certificate_extension_oid<1..2^8-1>;
          opaque certificate_extension_values<0..2^16-1>;
      } OIDFilter;

      struct {
          OIDFilter filters<0..2^16-1>;
      } OIDFilterExtension;

      struct {} PostHandshakeAuth;

      struct {
          Extension extensions<0..2^16-1>;
      } EncryptedExtensions;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          Extension extensions<2..2^16-1>;
      } CertificateRequest;
























Rescorla                     标准化进程                     [第 131 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.3.  认证消息

      enum {
          X509(0),
          OpenPGP_RESERVED(1),
          RawPublicKey(2),
          (255)
      } CertificateType;

      struct {
          select (certificate_type) {
              case RawPublicKey:
                /* From RFC 7250 ASN.1_subjectPublicKeyInfo */
                opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

              case X509:
                opaque cert_data<1..2^24-1>;
          };
          Extension extensions<0..2^16-1>;
      } CertificateEntry;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          CertificateEntry certificate_list<0..2^24-1>;
      } Certificate;

      struct {
          SignatureScheme algorithm;
          opaque signature<0..2^16-1>;
      } CertificateVerify;

      struct {
          opaque verify_data[Hash.length];
      } Finished;

B.3.4.  票据建立

      struct {
          uint32 ticket_lifetime;
          uint32 ticket_age_add;
          opaque ticket_nonce<0..255>;
          opaque ticket<1..2^16-1>;
          Extension extensions<0..2^16-2>;
      } NewSessionTicket;







Rescorla                     标准化进程                     [第 132 页]


RFC 8446                           TLS                       2018 年 8 月


B.3.5.  更新密钥

      struct {} EndOfEarlyData;

      enum {
          update_not_requested(0), update_requested(1), (255)
      } KeyUpdateRequest;

      struct {
          KeyUpdateRequest request_update;
      } KeyUpdate;

B.4.  密码套件

   对称密码套件定义了与 HKDF 一起使用的 AEAD 算法和哈希算法这一对。
   密码套件名称遵循以下命名约定:

      CipherSuite TLS_AEAD_HASH = VALUE;

      +-----------+------------------------------------------------+
      | 组成部分  | 内容                                           |
      +-----------+------------------------------------------------+
      | TLS       | 字符串“TLS”                                    |
      |           |                                                |
      | AEAD      | 用于记录保护的 AEAD 算法                       |
      |           |                                                |
      | HASH      | 与 HKDF 一起使用的哈希算法                     |
      |           |                                                |
      | VALUE     | 为此密码套件分配的两字节 ID                    |
      +-----------+------------------------------------------------+

   本规范定义了以下用于 TLS 1.3 的密码套件。

              +------------------------------+-------------+
              | 描述                         | 值          |
              +------------------------------+-------------+
              | TLS_AES_128_GCM_SHA256       | {0x13,0x01} |
              |                              |             |
              | TLS_AES_256_GCM_SHA384       | {0x13,0x02} |
              |                              |             |
              | TLS_CHACHA20_POLY1305_SHA256 | {0x13,0x03} |
              |                              |             |
              | TLS_AES_128_CCM_SHA256       | {0x13,0x04} |
              |                              |             |
              | TLS_AES_128_CCM_8_SHA256     | {0x13,0x05} |
              +------------------------------+-------------+



Rescorla                     标准化进程                     [第 133 页]


RFC 8446                           TLS                       2018 年 8 月


   对应的 AEAD 算法 AEAD_AES_128_GCM、AEAD_AES_256_GCM 和
   AEAD_AES_128_CCM 定义在 [RFC5116] 中。AEAD_CHACHA20_POLY1305
   定义在 [RFC8439] 中。AEAD_AES_128_CCM_8 定义在 [RFC6655] 中。
   对应的哈希算法定义在 [SHS] 中。

   尽管 TLS 1.3 使用与 TLS 先前版本相同的密码套件空间,但 TLS 1.3
   密码套件的定义方式不同,只指定对称密码,且不能用于 TLS 1.2。
   类似地,TLS 1.2 及以下版本的密码套件不能与 TLS 1.3 一起使用。

   新密码套件值由 IANA 按第 11 节所述分配。

附录 C.  实现说明

   TLS 协议无法防止许多常见安全错误。本附录提供若干建议以协助实现者。
   [TLS13-TRACES] 提供了 TLS 1.3 握手的测试向量。

C.1.  随机数生成和种子设定

   TLS 需要密码学安全的伪随机数生成器(CSPRNG)。在大多数情况下,
   操作系统会提供适当设施,例如 /dev/urandom,在没有其他(例如性能)
   考量时应使用它。RECOMMENDED 优先使用现有 CSPRNG 实现,而不是打造新
   实现。已有许多足够好的密码库以有利的许可条款提供。如果这些仍不令人
   满意,[RFC4086] 提供了关于随机值生成的指导。

   TLS 使用随机值:(1)用于公共协议字段,例如 ClientHello 和
   ServerHello 中的公共 Random 值;(2)用于生成密钥材料。在 CSPRNG
   正常工作的情况下,这不会带来安全问题,因为从其输出确定 CSPRNG 状态
   是不可行的。然而,在 CSPRNG 损坏的情况下,攻击者可能能够使用公共
   输出来确定 CSPRNG 内部状态,从而预测密钥材料,如 [CHECKOWAY] 中所
   记录。实现可以通过使用不同的 CSPRNG 来生成公共值和私有值,为这种
   攻击形式提供额外安全性。









Rescorla                     标准化进程                     [第 134 页]


RFC 8446                           TLS                       2018 年 8 月


C.2.  证书和认证

   实现负责验证证书完整性,并且通常应支持证书吊销消息。在没有来自应用
   配置文件的具体指示时,应始终验证证书,以确保它由受信任的证书颁发
   机构(CA)正确签名。选择和添加信任锚应非常谨慎。用户应能够查看关于
   证书和信任锚的信息。应用 SHOULD 还强制执行最小和最大密钥大小。例如,
   包含弱于 2048 位 RSA 或 224 位 ECDSA 的密钥或签名的认证路径,不适合
   安全应用。

C.3.  实现陷阱

   实现经验表明,早期 TLS 规范的某些部分并不容易理解,并且一直是
   互操作性和安全问题的来源。本文档已澄清其中许多领域,但本附录包含
   一份简短列表,列出需要实现者特别注意的最重要事项。

   TLS 协议问题:

   -  你是否正确处理分片到多个 TLS 记录中的握手消息(见第 5.1 节)?
      你是否正确处理诸如被拆分为多个小分片的 ClientHello 这样的边界
      情况?你是否会分片超过最大分片大小的握手消息?特别是,Certificate
      和 CertificateRequest 握手消息可能大到需要分片。

   -  你是否在所有未加密 TLS 记录中忽略 TLS 记录层版本号(见
      附录 D)?

   -  你是否已经确保,在支持 TLS 1.3 或更高版本的所有可能配置中,完全
      移除对 SSL、RC4、EXPORT 密码和 MD5(通过“signature_algorithms”
      扩展)的所有支持,并且尝试使用这些废弃能力会正确失败(见
      附录 D)?

   -  你是否正确处理 ClientHello 中的 TLS 扩展,包括未知扩展?







Rescorla                     标准化进程                     [第 135 页]


RFC 8446                           TLS                       2018 年 8 月


   -  当服务器请求了客户端证书但没有合适证书可用时,你是否正确发送空的
      Certificate 消息,而不是省略整条消息(见第 4.4.2 节)?

   -  当处理 AEAD-Decrypt 产生的明文分片,并从末尾扫描 ContentType 时,
      如果对等方发送了格式错误的全零明文,你是否避免扫描越过明文开头?

   -  你是否正确忽略 ClientHello 中未识别的密码套件(第 4.1.2 节)、
      hello 扩展(第 4.2 节)、命名组(第 4.2.7 节)、key
      share(第 4.2.8 节)、支持的版本(第 4.2.1 节)和签名算法
      (第 4.2.3 节)?

   -  作为服务器,对于支持兼容 (EC)DHE 组但未在“key_share”扩展中预测
      该组的客户端,你是否发送 HelloRetryRequest?作为客户端,你是否
      正确处理来自服务器的 HelloRetryRequest?

   密码学细节:

   -  你使用什么对策来防止定时攻击 [TIMING]?

   -  使用 Diffie-Hellman 密钥交换时,你是否正确保留协商密钥中的前导
      零字节(见第 7.4.1 节)?

   -  你的 TLS 客户端是否检查服务器发送的 Diffie-Hellman 参数是否可接受
      (见第 4.2.8.1 节)?

   -  在生成 Diffie-Hellman 私有值、ECDSA“k”参数和其他安全关键值时,
      你是否使用强且最重要的是正确播种的随机数生成器(见附录 C.1)?
      RECOMMENDED 实现按 [RFC6979] 指定实现“确定性 ECDSA”。

   -  你是否将 Diffie-Hellman 公钥值和共享秘密用零填充到组大小(见
      第 4.2.8.1 节第 7.4.1 节)?

   -  你是否在生成签名之后验证它们,以防止 RSA-CRT 密钥泄漏 [FW15]?









Rescorla                     标准化进程                     [第 136 页]


RFC 8446                           TLS                       2018 年 8 月


C.4.  客户端跟踪防止

   客户端 SHOULD NOT 在多个连接中重用票据。票据重用允许被动观察者关联
   不同连接。签发票据的服务器 SHOULD 至少提供与客户端可能使用的连接数
   一样多的票据;例如,使用 HTTP/1.1 [RFC7230] 的 Web 浏览器可能会
   打开到服务器的六个连接。服务器 SHOULD 在每个连接上签发新票据。这
   确保客户端在创建新连接时总能使用新票据。

C.5.  未认证操作

   TLS 的先前版本提供了基于匿名 Diffie-Hellman 的显式未认证密码套件。
   这些模式已在 TLS 1.3 中弃用。然而,仍然可以通过若干方法协商不提供
   可验证服务器认证的参数,包括:

   -  原始公钥 [RFC7250]。

   -  使用证书中包含的公钥,但不验证证书链或其任何内容。

   单独使用任一技术都容易受到中间人攻击,因此不适合一般用途。然而,也
   可以通过服务器公钥的带外验证、首次使用即信任,或诸如通道绑定这样的
   机制,将此类连接绑定到外部认证机制(尽管 [RFC5929] 中描述的通道
   绑定未为 TLS 1.3 定义)。如果不使用此类机制,则连接没有防护主动
   中间人攻击的能力;在没有显式配置或特定应用配置文件的情况下,应用
   MUST NOT 以这种方式使用 TLS。

















Rescorla                     标准化进程                     [第 137 页]


RFC 8446                           TLS                       2018 年 8 月


附录 D.  向后兼容性

   TLS 协议提供了一种内建机制,用于在可能支持不同 TLS 版本的端点之间
   进行版本协商。

   TLS 1.x 和 SSL 3.0 使用兼容的 ClientHello 消息。只要 ClientHello
   格式保持兼容,并且客户端和服务器至少共同支持一个协议版本,服务器也
   可以处理尝试使用 TLS 未来版本的客户端。

   TLS 的先前版本将记录层版本号(TLSPlaintext.legacy_record_version 和
   TLSCiphertext.legacy_record_version)用于各种目的。从 TLS 1.3 起,
   此字段已弃用。所有实现 MUST 忽略 TLSPlaintext.legacy_record_version
   的值。TLSCiphertext.legacy_record_version 的值包含在用于解除保护的
   additional data 中,但除此之外 MAY 被忽略,或 MAY 被验证为匹配固定
   常量值。版本协商只使用握手版本(ClientHello.legacy_version 和
   ServerHello.legacy_version,以及 ClientHello、HelloRetryRequest 和
   ServerHello 的“supported_versions”扩展)执行。为了最大化与较旧
   端点的互操作性,协商使用 TLS 1.0-1.2 的实现 SHOULD 将 ServerHello
   以及之后所有记录的记录层版本号设置为协商版本。

   为了与先前的非标准行为和错误配置部署最大兼容,所有实现 SHOULD 支持
   基于本文档中的预期来验证认证路径,即使是在处理先前 TLS 版本握手时
   也是如此(见第 4.4.2.2 节)。

   TLS 1.2 及先前版本支持“Extended Master Secret”[RFC7627] 扩展,
   该扩展将握手 transcript 的大部分内容摘要进主秘密。因为 TLS 1.3
   始终将直到服务器 Finished 的 transcript 哈希进去,所以同时支持
   TLS 1.3 和早期版本的实现,在使用 TLS 1.3 时 SHOULD 在其 API 中指示
   使用了 Extended Master Secret 扩展。











Rescorla                     标准化进程                     [第 138 页]


RFC 8446                           TLS                       2018 年 8 月


D.1.  与较旧服务器协商

   希望与不支持 TLS 1.3 的服务器协商的 TLS 1.3 客户端,会发送一个普通
   TLS 1.3 ClientHello,其中 ClientHello.legacy_version 包含 0x0303
   (TLS 1.2),但在“supported_versions”扩展中包含正确版本。如果服务器
   不支持 TLS 1.3,它将以包含较旧版本号的 ServerHello 响应。如果客户端
   同意使用该版本,协商将按所协商协议的适当方式继续。使用票据进行恢复
   的客户端 SHOULD 使用先前协商的版本发起连接。

   注意,0-RTT 数据与较旧服务器不兼容,并且在不知道服务器支持 TLS 1.3
   的情况下 SHOULD NOT 发送。见附录 D.3。

   如果服务器选择的版本不受客户端支持(或不可接受),客户端 MUST 使用
   “protocol_version”告警中止握手。

   已知某些遗留服务器实现没有正确实现 TLS 规范,并且在遇到它们不知道的
   TLS 扩展或版本时可能中止连接。与有缺陷服务器的互操作性是一个复杂
   主题,超出本文档范围。可能需要多次连接尝试才能协商向后兼容的连接;
   然而,此实践容易受到降级攻击,因此 NOT RECOMMENDED。

D.2.  与较旧客户端协商

   TLS 服务器也可能收到指示版本号小于其最高受支持版本的 ClientHello。
   如果存在“supported_versions”扩展,服务器 MUST 按第 4.2.1 节所述
   使用该扩展进行协商。如果不存在“supported_versions”扩展,服务器
   MUST 协商 ClientHello.legacy_version 和 TLS 1.2 中较小的一个。例如,
   如果服务器支持 TLS 1.0、1.1 和 1.2,并且 legacy_version 是 TLS 1.0,
   服务器将继续使用 TLS 1.0 ServerHello。如果“supported_versions”扩展
   不存在,并且服务器只支持大于 ClientHello.legacy_version 的版本,则
   服务器 MUST 使用“protocol_version”告警中止握手。

   注意,TLS 的早期版本并未在所有情况下清楚指定记录层版本号值
   (TLSPlaintext.legacy_record_version)。服务器会在此字段中收到各种
   TLS 1.x 版本,但其值 MUST 始终被忽略。




Rescorla                     标准化进程                     [第 139 页]


RFC 8446                           TLS                       2018 年 8 月


D.3.  0-RTT 向后兼容性

   0-RTT 数据与较旧服务器不兼容。较旧服务器会以较旧的 ServerHello
   响应 ClientHello,但它不会正确跳过 0-RTT 数据,并且无法完成握手。
   当客户端尝试使用 0-RTT 时,这可能造成问题,特别是面对多服务器部署时。
   例如,某个部署可能逐步部署 TLS 1.3,其中一些服务器实现 TLS 1.3,
   而另一些实现 TLS 1.2;或者 TLS 1.3 部署可能被降级到 TLS 1.2。

   尝试发送 0-RTT 数据的客户端如果收到 TLS 1.2 或更旧版本的 ServerHello,
   MUST 使该连接失败。然后它可以在禁用 0-RTT 的情况下重试连接。为了避免
   降级攻击,客户端 SHOULD NOT 禁用 TLS 1.3,而只禁用 0-RTT。

   为了避免这种错误条件,多服务器部署 SHOULD 在启用 0-RTT 之前,确保
   TLS 1.3(不带 0-RTT)的统一且稳定部署。

D.4.  中间盒兼容模式

   现场测量 [Ben17a] [Ben17b] [Res17a] [Res17b] 发现,当 TLS
   客户端/服务器对协商 TLS 1.3 时,大量中间盒会行为异常。实现可以通过
   使 TLS 1.3 握手看起来更像 TLS 1.2 握手,增加通过这些中间盒建立连接
   的机会:

   -  客户端始终在 ClientHello 中提供非空会话 ID,如第 4.1.2 节的
      legacy_session_id 部分所述。

   -  如果不提供 early data,客户端会在其第二趟消息之前立即发送一条
      哑 change_cipher_spec 记录(见第 5 节第三段)。这可以位于其
      第二个 ClientHello 之前,或位于其加密握手趟之前。如果提供
      early data,则该记录放在第一个 ClientHello 之后立即发送。

   -  服务器在其第一条握手消息之后立即发送一条哑 change_cipher_spec
      记录。这可以位于 ServerHello 或 HelloRetryRequest 之后。

   合在一起,这些更改使 TLS 1.3 握手类似于 TLS 1.2 会话恢复,从而提高
   通过中间盒成功连接的机会。此“兼容模式”是部分协商的:客户端可以选择
   是否提供会话 ID,而服务器必须回显它。任一端都可以在握手期间的任何
   时间发送



Rescorla                     标准化进程                     [第 140 页]


RFC 8446                           TLS                       2018 年 8 月


   change_cipher_spec,因为对等方必须忽略它们;但如果客户端发送非空
   会话 ID,服务器 MUST 按本附录所述发送 change_cipher_spec。

D.5.  与向后兼容性相关的安全限制

   在协商使用较旧 TLS 版本时,实现 SHOULD 优先选择前向保密和 AEAD
   密码套件(如果可用)。

   RC4 密码套件的安全性因 [RFC7465] 中引用的原因被认为不足。
   实现 MUST NOT 因任何理由为任何 TLS 版本提供或协商 RC4 密码套件。

   TLS 的旧版本允许使用强度非常低的密码。强度低于 112 位的密码 MUST NOT
   因任何理由为任何 TLS 版本提供或协商。

   SSL 3.0 [RFC6101] 的安全性因 [RFC7568] 中列举的原因被认为不足,
   并且 MUST NOT 因任何理由协商它。

   SSL 2.0 [SSL2] 的安全性因 [RFC6176] 中列举的原因被认为不足,
   并且 MUST NOT 因任何理由协商它。

   实现 MUST NOT 发送兼容 SSL 版本 2.0 的 CLIENT-HELLO。实现 MUST NOT
   使用兼容 SSL 版本 2.0 的 CLIENT-HELLO 协商 TLS 1.3 或更高版本。
   NOT RECOMMENDED 实现接受兼容 SSL 版本 2.0 的 CLIENT-HELLO 来协商
   TLS 的较旧版本。

   实现 MUST NOT 发送设置为 0x0300 或更小值的 ClientHello.legacy_version
   或 ServerHello.legacy_version。任何端点收到 ClientHello.legacy_version
   或 ServerHello.legacy_version 设置为 0x0300 的 Hello 消息时,MUST 使用
   “protocol_version”告警中止握手。

   实现 MUST NOT 发送任何版本小于 0x0300 的记录。实现 SHOULD NOT 接受
   任何版本小于 0x0300 的记录(但如果完全忽略记录版本号,则可能会无意
   中这样做)。

   实现 MUST NOT 使用[RFC6066] 第 7 节中定义的 Truncated HMAC 扩展,
   因为它不适用于 AEAD 算法,并且已被证明在某些场景下不安全。





Rescorla                     标准化进程                     [第 141 页]


RFC 8446                           TLS                       2018 年 8 月


附录 E.  安全属性概述

   对 TLS 的完整安全分析超出本文档范围。在本附录中,我们提供对期望属性
   的非正式描述,以及指向研究文献中更详细工作的参考,这些工作提供更
   正式的定义。

   我们分别覆盖握手属性和记录层属性。

E.1.  握手

   TLS 握手是一种认证密钥交换(AKE)协议,旨在同时提供单向认证(仅
   服务器)和相互认证(客户端和服务器)功能。在握手完成时,每一端都会
   输出它对以下值的看法:

   -  一组“会话密钥”(从主秘密派生出的各种秘密),可从中派生一组工作
      密钥。

   -  一组密码学参数(算法等)。

   -  通信各方的身份。

   我们假定攻击者是主动网络攻击者,这意味着它完全控制用于双方通信的
   网络 [RFC3552]。即使在这些条件下,握手也应提供下面列出的属性。
   注意,这些属性不一定相互独立,但反映了协议使用者的需求。

   建立相同会话密钥:只要每个端点上的握手都成功完成,握手就需要在握手
      双方输出相同的一组会话密钥(见 [CK01],定义 1,第 1 部分)。

   会话密钥的保密性:共享会话密钥应只为通信各方所知,而不为攻击者所知
      (见 [CK01],定义 1,第 2 部分)。注意,在单向认证连接中,
      攻击者可以与服务器建立自己的会话密钥,但这些会话密钥与客户端建立
      的会话密钥不同。

   对等方认证:客户端对对等方身份的看法应反映服务器的身份。如果客户端
      已认证,则服务器对对等方身份的看法应与客户端身份匹配。



Rescorla                     标准化进程                     [第 142 页]


RFC 8446                           TLS                       2018 年 8 月


   会话密钥的唯一性:任何两个不同握手都应产生不同且无关的会话密钥。
      由某次握手产生的各个会话密钥也应不同且独立。

   降级保护:密码学参数在双方应相同,并且应与对等方在没有攻击情况下
      通信时相同(见 [BBFGKZ16],定义 8 和 9)。

   相对于长期密钥的前向保密:如果长期密钥材料(在本例中为基于证书
      认证模式中的签名密钥,或带 (EC)DHE 的 PSK 模式中的外部/恢复 PSK)
      在握手完成后被攻破,只要会话密钥本身已被擦除,这不会危及会话密钥
      的安全性(见 [DOW92])。当在“psk_ke”PskKeyExchangeMode 中使用
      PSK 时,不满足前向保密属性。

   密钥泄露冒充(KCI)抵抗:在带证书的相互认证连接中,一个参与者的
      长期秘密被攻破,不应破坏该参与者在给定连接中对其对等方的认证
      (见 [HGFS15])。例如,如果客户端的签名密钥被攻破,之后的握手中
      不应能够向该客户端冒充任意服务器。

   端点身份保护:服务器身份(证书)应受到保护以抵御被动攻击者。客户端
      身份应受到保护以抵御被动和主动攻击者。

   非正式地,TLS 1.3 的基于签名的模式提供建立一个唯一、秘密、共享密钥
   的能力,该密钥通过 (EC)DHE 密钥交换建立,并由服务器对握手 transcript
   的签名认证,同时通过 MAC 绑定到服务器身份。如果客户端由证书认证,
   它也会对握手 transcript 签名,并提供绑定到双方身份的 MAC。[SIGMA]
   描述了这种密钥交换协议的设计和分析。如果每个连接都使用新的 (EC)DHE
   密钥,则输出密钥是前向保密的。

   外部 PSK 和恢复 PSK 从长期共享秘密引导出一组唯一的、每连接的短期
   会话密钥。此秘密可能是在先前握手中建立的。如果使用带 (EC)DHE 密钥
   建立的 PSK,这些会话密钥也将是前向保密的。恢复 PSK 已被设计成,
   连接 N 计算并用于形成连接 N+1 的恢复主秘密,与连接 N 使用的流量密钥



Rescorla                     标准化进程                     [第 143 页]


RFC 8446                           TLS                       2018 年 8 月


   分离,从而在连接之间提供前向保密。此外,如果在同一连接上建立多个
   票据,它们会与不同密钥关联,因此攻破与一个票据关联的 PSK 不会导致
   使用与其他票据关联的 PSK 建立的连接被攻破。如果票据存储在数据库中
   (因此可以被删除),而不是自加密,则此属性最有意义。

   PSK binder 值在 PSK 与当前握手之间,以及建立 PSK 的会话与当前会话
   之间形成绑定。此绑定传递性地包含原始握手 transcript,因为该
   transcript 会被摘要进产生恢复主秘密的值中。这要求用于产生恢复主秘密
   的 KDF 和用于计算 binder 的 MAC 都具有抗碰撞性。关于此内容的更多信息,
   见附录 E.1.1。注意:binder 不覆盖来自其他 PSK 的 binder 值,
   尽管它们包含在 Finished MAC 中。

   TLS 当前不允许服务器在非基于证书的握手(例如 PSK)中发送
   certificate_request 消息。如果未来放宽此限制,客户端签名将不会直接
   覆盖服务器证书。然而,如果 PSK 是通过 NewSessionTicket 建立的,客户端
   签名会通过 PSK binder 传递性地覆盖服务器证书。[PSK-FINISHED] 描述了
   一种针对未绑定服务器证书的构造的具体攻击(另见 [Kraw16])。
   当客户端可能与两个不同端点共享同一 PSK/key-id 对时,使用基于证书的
   客户端认证是不安全的。除非通过某个扩展协商,否则实现 MUST NOT 将
   外部 PSK 与客户端或服务器的基于证书认证组合使用。

   如果使用导出器,则它会产生唯一且秘密的值(因为它们从唯一会话密钥
   生成)。使用不同标签和上下文计算的导出器在计算上独立,因此无法从
   一个导出器计算另一个导出器,也无法从导出值计算会话秘密。注意:导出器
   可以产生任意长度的值;如果导出器要用作通道绑定,则导出值 MUST 足够大
   以提供抗碰撞性。TLS 1.3 中提供的导出器分别从与 early traffic key 和
   application traffic key 相同的 Handshake Context 派生,因此具有类似的
   安全属性。注意,它们不包含客户端证书;未来希望绑定到客户端证书的
   应用可能需要定义一种包含完整握手 transcript 的新导出器。



Rescorla                     标准化进程                     [第 144 页]


RFC 8446                           TLS                       2018 年 8 月


   对于所有握手模式,Finished MAC(以及存在时的签名)可防止降级攻击。
   此外,按第 4.1.3 节所述,在随机 nonce 中使用特定字节,可以
   检测降级到先前 TLS 版本。关于 TLS 1.3 和降级的更多细节,见
   [BBFGKZ16]。

   一旦客户端和服务器交换了足以建立共享密钥的信息,握手的其余部分就会
   被加密,从而提供抵御被动攻击者的保护,即使计算出的共享密钥未被认证。
   因为服务器先于客户端进行认证,所以客户端可以确保,如果它向服务器认证,
   它只会向已认证的服务器泄露其身份。注意,实现必须在握手期间使用所提供
   的记录填充机制,以避免由于长度泄露关于身份的信息。客户端提出的 PSK
   identity 不加密,服务器选择的那个也不加密。

E.1.1.  密钥派生和 HKDF

   TLS 1.3 中的密钥派生使用 [RFC5869] 中定义的 HKDF 及其两个组成部分
   HKDF-Extract 和 HKDF-Expand。HKDF 构造的完整理由可见 [Kraw10],
   而其在 TLS 1.3 中使用方式的理由可见 [KW16]。在本文档中,
   每次应用 HKDF-Extract 之后都会有一次或多次 HKDF-Expand 调用。应始终
   遵循此顺序(包括在本文档未来修订中);特别是,SHOULD NOT 在中间没有
   HKDF-Expand 的情况下,将 HKDF-Extract 的输出作为另一次 HKDF-Extract
   应用的输入。允许对某些相同输入多次应用 HKDF-Expand,只要通过密钥和/或
   标签区分它们即可。

   注意,HKDF-Expand 实现了一个输入和输出均为可变长度的伪随机函数
   (PRF)。在本文档中 HKDF 的某些用法中(例如,用于生成导出器和
   resumption_master_secret),需要 HKDF-Expand 的应用具有抗碰撞性;也就是说,
   找到两个不同的 HKDF-Expand 输入却输出相同值应是不可行的。这要求底层
   哈希函数具有抗碰撞性,并且 HKDF-Expand 的输出长度至少为 256 位(或
   哈希函数防止找到碰撞所需的长度)。








Rescorla                     标准化进程                     [第 145 页]


RFC 8446                           TLS                       2018 年 8 月


E.1.2.  客户端认证

   向服务器发送认证数据的客户端,无论是在握手期间还是在握手后认证中,
   都无法确定服务器随后是否认为客户端已认证。如果客户端需要确定服务器
   认为连接是单向认证还是相互认证,则必须由应用层提供此信息。详情见
   [CHHSV17]。此外,来自 [Kraw16] 的握手后认证分析表明,
   由握手后阶段发送的证书标识的客户端拥有流量密钥。因此,该方是参与
   原始握手的客户端,或是原始客户端向其委托了流量密钥的一方(假设流量
   密钥未被攻破)。

E.1.3.  0-RTT

   0-RTT 操作模式通常提供与 1-RTT 数据类似的安全属性,但有两个例外:
   0-RTT 加密密钥不提供完整前向保密,并且服务器在不保持可能过多状态的
   情况下无法保证握手唯一性(不可重放性)。限制重放暴露面的机制见
   第 8 节E.1.4.  导出器独立性

   exporter_master_secret 和 early_exporter_master_secret 被派生为独立于
   流量密钥,因此不会对使用这些密钥加密的流量安全性构成威胁。然而,
   因为这些秘密可用于计算任何导出器值,它们 SHOULD 尽快被擦除。如果
   导出器标签全集已知,则实现 SHOULD 为所有这些标签预先计算导出器计算的
   内部 Derive-Secret 阶段,然后擦除 [early_]exporter_master_secret,并在
   确知每个内部值不再需要时立即擦除它。

E.1.5.  攻破后安全性

   TLS 不为对等方长期秘密(签名密钥或外部 PSK)被攻破之后发生的握手
   提供安全性。因此,它不提供攻破后安全性 [CCG16],有时也称为后向
   保密或未来保密。这与 KCI 抵抗形成对比,后者描述的是一方自己的长期
   秘密被攻破后该方所具有的安全保证。




Rescorla                     标准化进程                     [第 146 页]


RFC 8446                           TLS                       2018 年 8 月


E.1.6.  外部参考文献

   读者应参考以下文献以了解 TLS 握手分析:[DFGS15]、[CHSV16]、
   [DFGS16]、[KW16]、[Kraw16]、[FGSW16]、
   [LXZFH16]、[FG17] 和 [BBK17]。

E.2.  记录层

   记录层依赖于握手产生强流量秘密,这些秘密可用于派生双向加密密钥和
   nonce。假设这一点成立,并且密钥使用的数据量不超过第 5.5 节中
   指出的数量,则记录层应提供以下保证:

   机密性:攻击者应无法确定给定记录的明文内容。

   完整性:攻击者应无法构造一条不同于现有记录、且会被接收方接受的新记录。

   顺序保护/不可重放性:攻击者应无法使接收方接受其已经接受过的记录,
      或使接收方在未先处理记录 N 的情况下接受记录 N+1。

   长度隐藏:给定一条具有某个外部长度的记录,攻击者应无法确定该记录中
      有多少是内容、有多少是填充。

   密钥更改后的前向保密:如果使用了第 4.6.3 节中描述的流量密钥
      更新机制,并删除了上一代密钥,则攻破端点的攻击者应无法解密使用
      旧密钥加密的流量。

   非正式地,TLS 1.3 通过使用强密钥对明文进行 AEAD 保护来提供这些属性。
   AEAD 加密 [RFC5116] 为数据提供机密性和完整性。不可重放性通过为每条记录
   使用单独 nonce 来提供,该 nonce 从记录序列号派生(第 5.3 节),
   而序列号在双方独立维护;因此,乱序交付的记录会导致 AEAD 解除保护
   失败。为了在相同明文由不同用户在相同密钥下反复加密(如 HTTP 中常见)
   时防止大规模密码分析,nonce 通过将





Rescorla                     标准化进程                     [第 147 页]


RFC 8446                           TLS                       2018 年 8 月


   序列号与随流量密钥一起派生的每连接秘密初始化向量混合而形成。关于
   此构造的分析,见 [BT16]。

   TLS 1.3 中的重新生成密钥技术(见第 7.2 节)遵循 [REKEY] 中讨论的
   串行生成器构造,该构造表明,重新生成密钥可以允许密钥用于比不重新
   生成密钥时更多的加密。这依赖于 HKDF-Expand-Label 函数作为伪随机函数
   (PRF)的安全性。此外,只要此函数确实是单向的,就无法计算密钥更改
   之前的流量密钥(前向保密)。

   TLS 不为连接的流量秘密被攻破后在该连接上传达的数据提供安全性。也就是说,
   对于流量秘密,TLS 不提供攻破后安全性/未来保密/后向保密。实际上,
   获知流量秘密的攻击者可以计算该连接上的所有未来流量秘密。想要这种
   保证的系统需要执行新的握手,并通过 (EC)DHE 交换建立新连接。

E.2.1.  外部参考文献

   读者应参考以下文献以了解 TLS 记录层分析:[BMMRT15]、
   [BT16]、[BDFKPPRSZZ16]、[BBK17] 和
   [PS18]。

E.3.  流量分析

   TLS 容易受到多种基于观察加密数据包长度和时序的流量分析攻击
   [CLINIC] [HCJC16]。当可区分的可能消息集合较小时,这尤其容易,例如托管固定
   内容语料库的视频服务器;但即使在更复杂的场景中,它仍会提供可用信息。

   TLS 不提供针对这种攻击形式的任何具体防御,但包含一个供应用使用的
   填充机制:由 AEAD 函数保护的明文由内容加可变长度填充组成,这允许
   应用产生任意长度的加密记录,以及仅填充的掩护流量,以隐藏传输期间和
   静默期间之间的差异。由于填充与实际内容一起加密,攻击者无法直接确定
   填充长度,但可能能够通过记录处理期间暴露的定时信道间接测量它(即,
   观察处理记录需要多长时间,或缓慢送入记录以查看



Rescorla                     标准化进程                     [第 148 页]


RFC 8446                           TLS                       2018 年 8 月


   哪些记录会引发服务器响应)。一般而言,尚不清楚如何移除所有这些信道,
   因为即使常量时间的填充移除函数也可能将内容输入到数据依赖函数中。
   至少,完全常量时间的服务器或客户端需要与应用层协议实现密切配合,
   包括使该更高层协议也为常量时间。

   注意:稳健的流量分析防御很可能因传输数据包延迟和流量量增加而导致
   性能降低。

E.4.  侧信道攻击

   一般而言,TLS 没有针对侧信道攻击(即通过诸如定时等次级信道攻击通信)
   的具体防御,而是将这些留给相关密码原语的实现。然而,TLS 的某些特性
   旨在更容易编写抗侧信道代码:

   -  与使用复合 MAC-then-encrypt 结构的 TLS 先前版本不同,TLS 1.3 只使用
      AEAD 算法,允许实现使用这些原语的自包含常量时间实现。

   -  TLS 对所有解密错误使用统一的“bad_record_mac”告警,旨在防止攻击者
      分段洞察消息的各部分。通过在此类错误上终止连接提供额外抵抗力;
      新连接将具有不同的密码材料,从而防止需要多次试验的针对密码原语的
      攻击。

   通过侧信道发生的信息泄露可能出现在 TLS 之上的层中,即应用协议和使用
   它们的应用中。对侧信道攻击的抵抗取决于应用和应用协议分别确保机密
   信息不会被无意泄露。













Rescorla                     标准化进程                     [第 149 页]


RFC 8446                           TLS                       2018 年 8 月


E.5.  针对 0-RTT 的重放攻击

   可重放的 0-RTT 数据会给使用 TLS 的应用带来许多安全威胁,除非这些
   应用被专门设计为在重放下安全(最低限度,这意味着幂等,但在许多情况下
   也可能需要其他更强条件,例如常量时间响应)。潜在攻击包括:

   -  复制会造成副作用的操作(例如购买物品或转账),从而损害站点或用户。

   -  攻击者可以存储并重放 0-RTT 消息,以便相对于其他消息重新排序它们
      (例如,将删除移动到创建之后)。

   -  利用缓存定时行为,通过向不同缓存节点重放 0-RTT 消息,然后使用单独
      连接测量请求延迟,查看两个请求是否寻址同一资源,从而发现 0-RTT
      消息的内容。

   如果数据可以被大量重放,则其他攻击会成为可能,例如反复测量密码操作
   速度。此外,它们可能会使速率限制系统过载。关于这些攻击的进一步描述,
   见 [Mac17]。

   最终,服务器有责任保护自己免受采用 0-RTT 数据复制的攻击。
   第 8 节中描述的机制旨在防止 TLS 层的重放,但不能提供对接收
   客户端数据多个副本的完全保护。当服务器没有关于客户端的任何信息时,
   例如因为它位于不共享状态的不同集群中,或因为票据已按第 8.1 节
   所述被删除,TLS 1.3 会回退到 1-RTT 握手。如果应用层协议在这种场景中
   重传数据,则攻击者可能通过将 ClientHello 同时发送到原始集群(立即处理
   数据)和另一个将回退到 1-RTT 并在应用层重放时处理数据的集群,诱发
   消息重复。此攻击的规模受限于客户端重试事务的意愿,因此只允许有限量
   重复,每个副本在服务器看来都是一个新连接。







Rescorla                     标准化进程                     [第 150 页]


RFC 8446                           TLS                       2018 年 8 月


   如果正确实现,第 8.1 节和 8.2 中描述的机制会防止被重放的
   ClientHello 及其关联 0-RTT 数据被任何具有一致状态的集群多次接受;
   对于将 0-RTT 使用限制为单个票据对应单个集群的服务器,给定 ClientHello
   及其关联 0-RTT 数据只会被接受一次。然而,如果状态并非完全一致,
   攻击者可能能够在复制窗口期间让数据的多个副本被接受。因为客户端不知道
   服务器行为的确切细节,所以它们 MUST NOT 在 early data 中发送不适合
   重放、且它们不愿意跨多个 1-RTT 连接重试的消息。

   应用协议 MUST NOT 在没有定义其用法的配置文件时使用 0-RTT 数据。该
   配置文件需要识别哪些消息或交互可安全地与 0-RTT 一起使用,以及当服务器
   拒绝 0-RTT 并回退到 1-RTT 时如何处理。

   此外,为了避免意外误用,TLS 实现 MUST NOT 启用 0-RTT(无论发送还是
   接受),除非应用明确请求;如果服务器拒绝 0-RTT 数据,TLS 实现 MUST NOT
   自动重新发送它,除非应用指示这样做。服务器侧应用可能希望对某些类型的
   应用流量实现针对 0-RTT 数据的特殊处理(例如,中止连接、请求在应用层
   重新发送数据,或延迟处理直到握手完成)。为了允许应用实现这种处理,
   TLS 实现 MUST 提供一种方式,让应用确定握手是否已完成。

E.5.1.  重放和导出器

   ClientHello 的重放会产生相同的 early exporter,因此使用这些导出器的
   应用需要额外小心。特别是,如果这些导出器用作认证通道绑定(例如,通过
   签署导出器输出),则攻破 PSK 的攻击者可以在不攻破认证密钥的情况下,
   在连接之间移植认证器。

   此外,early exporter SHOULD NOT 用于生成服务器到客户端的加密密钥,
   因为那会导致这些密钥被重用。这与 early application traffic key 只在
   客户端到服务器方向使用相对应。









Rescorla                     标准化进程                     [第 151 页]


RFC 8446                           TLS                       2018 年 8 月


E.6.  PSK Identity 暴露

   由于实现会通过中止握手来响应无效 PSK binder,攻击者可能能够验证给定
   PSK identity 是否有效。具体而言,如果服务器同时接受 external-PSK
   握手和基于证书的握手,有效的 PSK identity 会导致握手失败,而无效
   identity 只会被跳过,并导致成功的证书握手。只支持 PSK 握手的服务器
   可以通过将没有有效 PSK identity 的情况与存在 identity 但其 binder
   无效的情况等同处理,来抵抗这种攻击形式。

E.7.  共享 PSK

   TLS 1.3 对 PSK 采取保守方法,将它们绑定到特定 KDF。相比之下,
   TLS 1.2 允许 PSK 与任何哈希函数和 TLS 1.2 PRF 一起使用。因此,任何
   同时与 TLS 1.2 和 TLS 1.3 一起使用的 PSK,在 TLS 1.3 中必须只与一个
   哈希一起使用;如果用户希望提供单个 PSK,这并非最优。TLS 1.2 和
   TLS 1.3 中的构造不同,尽管它们都基于 HMAC。虽然没有已知方式使同一
   PSK 在两个版本中产生相关输出,但只进行了有限分析。实现可以通过不在
   TLS 1.3 和 TLS 1.2 之间重用 PSK,确保免受跨协议相关输出影响。

E.8.  针对静态 RSA 的攻击

   尽管 TLS 1.3 不使用 RSA 密钥传输,因此不会直接受到 Bleichenbacher
   类型攻击 [Blei98] 的影响,但如果 TLS 1.3 服务器也在 TLS 先前版本的
   上下文中支持静态 RSA,则可能冒充服务器进行 TLS 1.3 连接 [JSS15]。
   TLS 1.3 实现可以通过在所有 TLS 版本中禁用静态 RSA 支持来防止此攻击。
   原则上,实现也可能能够为静态 RSA 解密和 RSA 签名分离具有不同 keyUsage
   位的证书,但此技术依赖于客户端拒绝接受使用证书中未设置 digitalSignature
   位的密钥进行的签名,而许多客户端并不强制执行此限制。










Rescorla                     标准化进程                     [第 152 页]


RFC 8446                           TLS                       2018 年 8 月


贡献者

   Martin Abadi
   University of California, Santa Cruz
   abadi@cs.ucsc.edu

   Christopher Allen
   (TLS 1.0 的共同编辑)
   Alacrity Ventures
   ChristopherA@AlacrityManagement.com

   Richard Barnes
   Cisco
   rlb@ipv.sx

   Steven M. Bellovin
   Columbia University
   smb@cs.columbia.edu

   David Benjamin
   Google
   davidben@google.com

   Benjamin Beurdouche
   INRIA & Microsoft Research
   benjamin.beurdouche@ens.fr

   Karthikeyan Bhargavan
   ([RFC7627] 的编辑)
   INRIA
   karthikeyan.bhargavan@inria.fr

   Simon Blake-Wilson
   ([RFC4492] 的共同作者)
   BCI
   sblakewilson@bcisse.com

   Nelson Bolyard
   ([RFC4492] 的共同作者)
   Sun Microsystems, Inc.
   nelson@bolyard.com

   Ran Canetti
   IBM
   canetti@watson.ibm.com






Rescorla                     标准化进程                     [第 153 页]


RFC 8446                           TLS                       2018 年 8 月


   Matt Caswell
   OpenSSL
   matt@openssl.org

   Stephen Checkoway
   University of Illinois at Chicago
   sfc@uic.edu

   Pete Chown
   Skygate Technology Ltd
   pc@skygate.co.uk

   Katriel Cohn-Gordon
   University of Oxford
   me@katriel.co.uk

   Cas Cremers
   University of Oxford
   cas.cremers@cs.ox.ac.uk

   Antoine Delignat-Lavaud
   ([RFC7627] 的共同作者)
   INRIA
   antdl@microsoft.com

   Tim Dierks
   (TLS 1.0 的共同作者,TLS 1.1 和 1.2 的共同编辑)
   Independent
   tim@dierks.org

   Roelof DuToit
   Symantec Corporation
   roelof_dutoit@symantec.com

   Taher Elgamal
   Securify
   taher@securify.com

   Pasi Eronen
   Nokia
   pasi.eronen@nokia.com

   Cedric Fournet
   Microsoft
   fournet@microsoft.com






Rescorla                     标准化进程                     [第 154 页]


RFC 8446                           TLS                       2018 年 8 月


   Anil Gangolli
   anil@busybuddha.org

   David M. Garrett
   dave@nulldereference.com

   Illya Gerasymchuk
   Independent
   illya@iluxonchik.me

   Alessandro Ghedini
   Cloudflare Inc.
   alessandro@cloudflare.com

   Daniel Kahn Gillmor
   ACLU
   dkg@fifthhorseman.net

   Matthew Green
   Johns Hopkins University
   mgreen@cs.jhu.edu

   Jens Guballa
   ETAS
   jens.guballa@etas.com

   Felix Guenther
   TU Darmstadt
   mail@felixguenther.info

   Vipul Gupta
   ([RFC4492] 的共同作者)
   Sun Microsystems Laboratories
   vipul.gupta@sun.com

   Chris Hawk
   ([RFC4492] 的共同作者)
   Corriente Networks LLC
   chris@corriente.net

   Kipp Hickman

   Alfred Hoenes

   David Hopwood
   Independent Consultant
   david.hopwood@blueyonder.co.uk




Rescorla                     标准化进程                     [第 155 页]


RFC 8446                           TLS                       2018 年 8 月


   Marko Horvat
   MPI-SWS
   mhorvat@mpi-sws.org

   Jonathan Hoyland
   Royal Holloway, University of London
   jonathan.hoyland@gmail.com

   Subodh Iyengar
   Facebook
   subodh@fb.com

   Benjamin Kaduk
   Akamai Technologies
   kaduk@mit.edu

   Hubert Kario
   Red Hat Inc.
   hkario@redhat.com

   Phil Karlton
   (SSL 3.0 的共同作者)

   Leon Klingele
   Independent
   mail@leonklingele.de

   Paul Kocher
   (SSL 3.0 的共同作者)
   Cryptography Research
   paul@cryptography.com

   Hugo Krawczyk
   IBM
   hugokraw@us.ibm.com

   Adam Langley
   ([RFC7627] 的共同作者)
   Google
   agl@google.com

   Olivier Levillain
   ANSSI
   olivier.levillain@ssi.gouv.fr







Rescorla                     标准化进程                     [第 156 页]


RFC 8446                           TLS                       2018 年 8 月


   Xiaoyin Liu
   University of North Carolina at Chapel Hill
   xiaoyin.l@outlook.com

   Ilari Liusvaara
   Independent
   ilariliusvaara@welho.com

   Atul Luykx
   K.U. Leuven
   atul.luykx@kuleuven.be

   Colm MacCarthaigh
   Amazon Web Services
   colm@allcosts.net

   Carl Mehner
   USAA
   carl.mehner@usaa.com

   Jan Mikkelsen
   Transactionware
   janm@transactionware.com

   Bodo Moeller
   ([RFC4492] 的共同作者)
   Google
   bodo@acm.org

   Kyle Nekritz
   Facebook
   knekritz@fb.com

   Erik Nygren
   Akamai Technologies
   erik+ietf@nygren.org

   Magnus Nystrom
   Microsoft
   mnystrom@microsoft.com

   Kazuho Oku
   DeNA Co., Ltd.
   kazuhooku@gmail.com







Rescorla                     标准化进程                     [第 157 页]


RFC 8446                           TLS                       2018 年 8 月


   Kenny Paterson
   Royal Holloway, University of London
   kenny.paterson@rhul.ac.uk

   Christopher Patton
   University of Florida
   cjpatton@ufl.edu

   Alfredo Pironti
   ([RFC7627] 的共同作者)
   INRIA
   alfredo.pironti@inria.fr

   Andrei Popov
   Microsoft
   andrei.popov@microsoft.com

   Marsh Ray
   ([RFC7627] 的共同作者)
   Microsoft
   maray@microsoft.com

   Robert Relyea
   Netscape Communications
   relyea@netscape.com

   Kyle Rose
   Akamai Technologies
   krose@krose.org

   Jim Roskind
   Amazon
   jroskind@amazon.com

   Michael Sabin

   Joe Salowey
   Tableau Software
   joe@salowey.net

   Rich Salz
   Akamai
   rsalz@akamai.com

   David Schinazi
   Apple Inc.
   dschinazi@apple.com




Rescorla                     标准化进程                     [第 158 页]


RFC 8446                           TLS                       2018 年 8 月


   Sam Scott
   Royal Holloway, University of London
   me@samjs.co.uk

   Thomas Shrimpton
   University of Florida
   teshrim@ufl.edu

   Dan Simon
   Microsoft, Inc.
   dansimon@microsoft.com

   Brian Smith
   Independent
   brian@briansmith.org

   Brian Sniffen
   Akamai Technologies
   ietf@bts.evenmere.org

   Nick Sullivan
   Cloudflare Inc.
   nick@cloudflare.com

   Bjoern Tackmann
   University of California, San Diego
   btackmann@eng.ucsd.edu

   Tim Taubert
   Mozilla
   ttaubert@mozilla.com

   Martin Thomson
   Mozilla
   mt@mozilla.com

   Hannes Tschofenig
   Arm Limited
   Hannes.Tschofenig@arm.com

   Sean Turner
   sn3rd
   sean@sn3rd.com

   Steven Valdez
   Google
   svaldez@google.com




Rescorla                     标准化进程                     [第 159 页]


RFC 8446                           TLS                       2018 年 8 月


   Filippo Valsorda
   Cloudflare Inc.
   filippo@cloudflare.com

   Thyla van der Merwe
   Royal Holloway, University of London
   tjvdmerwe@gmail.com

   Victor Vasiliev
   Google
   vasilvv@google.com

   Hoeteck Wee
   Ecole Normale Superieure, Paris
   hoeteck@alum.mit.edu

   Tom Weinstein

   David Wong
   NCC Group
   david.wong@nccgroup.trust

   Christopher A. Wood
   Apple Inc.
   cawood@apple.com

   Tim Wright
   Vodafone
   timothy.wright@vodafone.com

   Peter Wu
   Independent
   peter@lekensteyn.nl

   Kazu Yamamoto
   Internet Initiative Japan Inc.
   kazu@iij.ad.jp

作者地址

   Eric Rescorla
   Mozilla

   电子邮件:ekr@rtfm.com







Rescorla                     标准化进程                     [第 160 页]