Internet Engineering Task Force (IETF) R. Polli
Request for Comments: 9530 Team Digitale, Italian Government
Obsoletes: 3230 L. Pardue
Category: Standards Track Cloudflare
ISSN: 2070-1721 February 2024

Digest Fields


摘要

本文档定义了支持完整性摘要的 HTTP 字段。Content-Digest 字段可用于 HTTP 消息内容的完整性。Repr-Digest 字段可用于 HTTP 表示的完整性。Want-Content-DigestWant-Repr-Digest 可用于指示发送方对接收相应完整性字段的兴趣与偏好。

本文档废弃了 RFC 3230 以及 DigestWant-Digest HTTP 字段。

本文备忘录的状态

这是一个 Internet 标准轨道文档。

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

有关本文档当前状态、任何勘误以及如何对其提供反馈的信息,请访问 https://www.rfc-editor.org/info/rfc9530

Copyright Notice

Copyright (c) 2024 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 Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.


1. 介绍

HTTP 并未定义保护内容或表示数据完整性的手段。当 HTTP 消息在端点之间传输时,诸如 TCP 校验和或 TLS 记录 [TLS] 等下层特性或属性可以提供某种完整性保护。然而,面向传输的完整性对应用层是不透明的,并且仅覆盖单个连接的范围,因此其实用性有限。HTTP 消息经常通过一系列独立连接传输;在连接之间,存在数据损坏的可能性。HTTP 完整性机制可以为端点或使用 HTTP 的应用提供检测数据损坏的手段,并据此决定如何处理。例如,可用于跨系统边界辅助故障检测与诊断的用例。

本文档为 HTTP 定义了两种摘要完整性机制。第一种是内容完整性,作用于传输的内容(参见 [HTTP] 第 6.4 节)。第二种是表示数据完整性,作用于表示数据(参见 [HTTP] 第 8.1 节)。这支持例如验证从多个请求或连接检索并重建的资源的完整性等高级用例。

本文档废弃了 [RFC3230],因此也废弃了 DigestWant-Digest HTTP 字段;参见 第 1.3 节

1.1. 文档结构

本文档的结构如下:

  • 新的请求与响应头字段及尾部字段定义。

  • 与表示数据完整性相关的特定考虑。

    • 第 3.1 节 (有状态变更请求),
    • 第 3.2 节(Content-Location),
    • 附录 A 包含了消息交换中关于表示数据的示例,以及
    • 附录 BC 包含了 Repr-DigestWant-Repr-Digest 在消息交换中的示例。
  • 第 5 节 提出哈希算法的考虑并定义未来条目的注册流程。

1.2. 概念概述

本文档定义的 HTTP 字段可用于实现 HTTP 完整性。发送方选择哈希算法并基于与 HTTP 消息相关的输入计算摘要。算法标识符与摘要在 HTTP 字段中传输。接收方可以验证摘要以实现完整性检查。哈希算法在 “Hash Algorithms for HTTP Digest Fields” 注册表中注册(参见 第 7.2 节)。

选择用于计算摘要的数据取决于 HTTP 消息的用例。本文档为 HTTP 表示数据与 HTTP 内容提供了不同的字段。

在某些用例中,仅需对 HTTP 内容字节做简单摘要。Content-Digest 请求与响应头以及尾部字段被定义用于支持对内容的摘要(参见 [HTTP] 第 6.4 节);详见 第 2 节

对于更高级的用例,定义了 Repr-Digest 请求与响应头以及尾部字段(参见 第 3 节)。它包含通过对选定的表示数据应用哈希算法计算得到的摘要值(参见 [HTTP] 第 8.1 节)。基于选定表示的 Repr-Digest 便于将其应用到需要对消息内容进行某种处理后才视作资源表示,或内容表示资源的部分表示(例如范围请求,参见 [HTTP] 第 14 节)的用例。

Content-DigestRepr-Digest 支持哈希算法的可替换性。Want-Content-DigestWant-Repr-Digest 字段允许端点分别表达对接收 Content-DigestRepr-Digest 的兴趣,并可在其中表达算法偏好。

Content-DigestRepr-Digest 合称为“完整性字段”。Want-Content-DigestWant-Repr-Digest 合称为“完整性偏好字段”。

完整性字段与 Content-EncodingContent-Type 头字段相关联。因此,当通过 HTTP 传输时,同一资源可能具有多个不同的摘要值。

完整性字段适用于 HTTP 消息的内容或 HTTP 表示;它们不适用于 HTTP 消息或消息字段本身。然而,它们可以与保护元数据的其它机制(例如数字签名)结合使用,从而对 HTTP 交换的阶段性或整体提供保护。例如,可以使用 HTTP Message Signatures [SIGNATURES] 对完整性字段进行签名,从而为 HTTP 内容或表示数据提供覆盖保护。

本规范不定义身份验证、授权或隐私的手段。

1.3. 废弃 RFC 3230

[RFC3230] 定义了用于 HTTP 完整性的 DigestWant-Digest 字段,并引入了“instance”(实例)与“instance manipulation”(实例处理)等术语以解释诸如选定表示数据(参见 [HTTP] 第 8.1 节)之类的概念,这些概念现在已作为 HTTP 语义更通用地定义并实现。

实践表明,对 [RFC3230] 的实现对“instance”含义的解释不一致,导致互操作性问题。最常见的问题是错误地使用(即现在称为)消息内容来计算摘要,而不是使用(即现在称为)表示数据,尽管后者为最初的意图。有趣的是,时间也表明对消息内容的摘要在某些用例中是有益的,因此难以判断对 [RFC3230] 的不一致实现是出于有意还是无意。

为了解决 DigestWant-Digest 的实现间潜在不一致与歧义,本文档废弃了 [RFC3230]。本文档中定义的完整性字段(第 2 节 与第 3 节)以及完整性偏好字段(第 4 节)更好地与当前 HTTP 语义对齐,且其名称更清晰地表达了预期用法。

1.4. 表示法约定

文中关键字 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY" 和 "OPTIONAL" 的解释,见 BCP 14(参见 [RFC2119][RFC8174]),仅当这些词以全部大写形式出现时按该定义解释。

本文档使用在 [RFC5234] 中定义并经 [RFC7405] 更新的增强 BNF(ABNF)。这包括规则 CR(回车)、LF(换行)与 CRLF(回车换行)。

本文档使用 [STRUCTURED-FIELDS] 第 3 节 中的术语来指定语法与解析:Boolean、Byte Sequence、Dictionary、Integer 和 List。

文中对术语 “representation”、“selected representation”、“representation data”、“representation metadata”、“user agent” 与 “content” 的定义,应按 [HTTP] 的描述理解。

本文档使用 [FOLDING] 中描述的行折叠策略。

哈希算法名称应尊重其定义文档中使用的大小写(例如 SHA-1、CRC32c)。

HTTP 消息使用 Algorithm Key(算法键)来指示哈希算法。文中若以散文提及 Algorithm Key,则使用引号(例如 "sha", "crc32c")。

术语 “checksum” 描述将算法应用于字节序列所产生的输出,而 “digest” 仅用于字段中包含的值。

“完整性字段” 为 Content-DigestRepr-Digest 的集合称谓。

“完整性偏好字段” 为 Want-Repr-DigestWant-Content-Digest 的集合称谓。


2.  Content-Digest 字段

Content-Digest HTTP 字段可用于请求和响应中,用来传达对实际消息内容应用哈希算法后计算得到的摘要(参见 [HTTP] 第 6.4 节)。它的类型为 Dictionary(参见 [STRUCTURED-FIELDS] 第 3.2 节),其中每个:

  • key 表示用于计算摘要的哈希算法(参见 第 5 节);
  • value 是一个 Byte Sequence(参见 [STRUCTURED-FIELDS] 第 3.3.5 节),用于传达摘要计算所产生的字节输出的编码形式。

例如:

NOTE: '\' line wrapping per RFC 8792

Content-Digest: \
  sha-512=:YMAam51Jz/jOATT6/zvHrLVgOYTGFy1d6GJiOHTohq4yP+pgk4vf2aCs\
  yRZOtw8MjkM7iw7yZ/WkppmM44T3qg==:

Dictionary 类型可用于附加使用不同哈希算法计算的多个摘要,以支持具有不同或不断演进能力的端点群体。此类方法可支持从较弱算法向更强算法的过渡(参见 第 6.6 节)。

NOTE: '\' line wrapping per RFC 8792

Content-Digest: \
  sha-256=:d435Qo+nKZ+gLcUHn7GQtQ72hiBVAgqoLsZnZPiTGPk=:,\
  sha-512=:YMAam51Jz/jOATT6/zvHrLVgOYTGFy1d6GJiOHTohq4yP+pgk4vf2aCs\
  yRZOtw8MjkM7iw7yZ/WkppmM44T3qg==:

接收方 MAY 忽略任意或全部摘要。特定应用行为或本地策略 MAY 对传达的摘要的处理与验证实践设定额外限制。安全注意事项讨论了与忽略摘要(参见 第 6.6 节)与验证多个摘要(参见 第 6.7 节)相关的问题。

发送方 MAY 在不知接收方是否支持某一哈希算法的情况下发送摘要。发送方 MAY 在知晓接收方会忽略该摘要时仍发送之。

Content-Digest 可在尾部(trailer)节中发送。在此情况下,Content-Digest MAY 被合并到头部节中;参见 [HTTP] 第 6.5.1 节


3.  Repr-Digest 字段

Repr-Digest HTTP 字段可用于请求和响应中,用来传达对整个选定表示数据应用哈希算法后计算得到的摘要(参见 [HTTP] 第 8.1 节)。

表示(representations)考虑了 HTTP 语义对消息的影响。例如,内容可能会受到范围请求或诸如 HEAD 这类方法的影响,而内容在“线上”的传输方式依赖于其它转换(例如 HTTP/1.1 的传输编码;参见 [HTTP/1.1] 第 6.1 节)。为帮助说明 HTTP 表示的概念,附录 A 提供了若干示例。

当消息没有表示数据时,仍然可以通过对空字符串计算摘要来断言未发送表示数据(参见 第 6.3 节)。

Repr-Digest 的类型为 Dictionary(参见 [STRUCTURED-FIELDS] 第 3.2 节),其中每个:

  • key 表示用于计算摘要的哈希算法(参见 第 5 节);
  • value 是一个 Byte Sequence,用于传达摘要计算生成的字节输出的编码形式。

例如:

NOTE: '\' line wrapping per RFC 8792

Repr-Digest: \
  sha-512=:YMAam51Jz/jOATT6/zvHrLVgOYTGFy1d6GJiOHTohq4yP+pgk4vf2aCs\
  yRZOtw8MjkM7iw7yZ/WkppmM44T3qg==:

Dictionary 类型可用于附加使用不同哈希算法计算的多个摘要,以支持具有不同或不断演进能力的端点群体。此类方法可支持从较弱算法向更强算法的过渡(参见 第 6.6 节)。

NOTE: '\' line wrapping per RFC 8792

Repr-Digest: \
  sha-256=:d435Qo+nKZ+gLcUHn7GQtQ72hiBVAgqoLsZnZPiTGPk=:,\
  sha-512=:YMAam51Jz/jOATT6/zvHrLVgOYTGFy1d6GJiOHTohq4yP+pgk4vf2aCs\
  yRZOtw8MjkM7iw7yZ/WkppmM44T3qg==:

接收方 MAY 忽略任意或全部摘要。特定应用行为或本地策略 MAY 对传达的摘要的处理与验证实践设定额外限制。安全注意事项讨论了与忽略摘要(参见 第 6.6 节)与验证多个摘要(参见 第 6.7 节)相关的问题。

发送方 MAY 在不知接收方是否支持某一哈希算法的情况下发送摘要。发送方 MAY 在知晓接收方会忽略该摘要时仍发送之。

Repr-Digest 可在尾部(trailer)节中发送。在此情况下,Repr-Digest MAY 被合并到头部节中;参见 [HTTP] 第 6.5.1 节

3.1. 在有状态变更请求中使用 Repr-Digest

当封装在有状态变更请求中的表示并不描述目标资源时,表示摘要 MUST 在表示数据上计算。这是唯一可行的选择,因为表示摘要要求完整的表示元数据(参见 第 3 节)。

在响应中,

  • 如果该表示描述了请求的状态,Repr-Digest MUST 在所封装的表示上计算(见 附录 B.8);
  • 如果存在被引用的资源,Repr-Digest MUST 在被引用资源的选定表示上计算,即便该表示与目标资源不同。此情况可能导致对封装表示或不对封装表示计算 Repr-Digest

后一种情况应根据给定方法的 HTTP 语义执行,例如使用 Content-Location 头字段(参见 [HTTP] 第 8.7 节)。相反,Location 头字段不影响 Repr-Digest,因为它并非表示元数据。

例如,在 PATCH 请求中,表示摘要将对补丁文档计算,因为表示元数据指向的是补丁文档而非目标资源(参见 [PATCH] 第 2 节)。而在响应中,表示摘要将对被修补资源的选定表示计算。

3.2. Repr-Digest 与响应中的 Content-Location

当有状态变更方法返回 Content-Location 头字段时,所封装的表示指代由该字段值标识的资源,并应据此计算 Repr-Digest。示例见 附录 B.7


4. 完整性偏好字段

发送方可以使用 Want-Content-DigestWant-Repr-Digest HTTP 字段来指示其对完整性字段的兴趣以及哈希算法偏好。这些字段可以在请求和响应中使用。

Want-Content-Digest 表示发送方希望接收(通过 Content-Digest 字段)与请求 URI 和表示元数据相关联的消息的内容摘要。Want-Repr-Digest 表示发送方希望接收(通过 Repr-Digest 字段)与请求 URI 和表示元数据相关联的消息的表示摘要。

如果在响应中使用 Want-Content-DigestWant-Repr-Digest,则表示服务器希望客户端在未来的请求中提供相应的完整性字段。

完整性偏好字段仅为提示。字段的接收方可以忽略该提示,并使用任意算法发送完整性字段或完全省略该字段;例如,参见 附录 C.2。忽略偏好并不是协议错误。使用完整性字段和完整性偏好的应用可以定义除本规范之外的期望或约束。被忽略的偏好属于应用特定的事项。

Want-Content-DigestWant-Repr-Digest 的类型为 Dictionary,其中每个:

  • key 表示用于计算摘要的哈希算法(参见 第 5 节);
  • value 是一个 Integer(参见 [STRUCTURED-FIELDS] 第 3.3.1 节),表示一个递增的相对加权偏好。其取值范围必须为 0 到 10(含)。1 为最不偏好,10 为最偏好,值 0 表示“不接受”。

示例:

Want-Repr-Digest: sha-256=1
Want-Repr-Digest: sha-512=3, sha-256=10, unixsum=0
Want-Content-Digest: sha-256=1
Want-Content-Digest: sha-512=3, sha-256=10, unixsum=0

5. 哈希算法的考虑与注册

用于完整性的哈希算法有多种选择。算法的选择取决于若干因素,例如完整性用例、实现的需求或约束,或应用的设计与工作流。

初始的一组算法将由 IANA 在 “Hash Algorithms for HTTP Digest Fields” 注册表中注册;参见 第 7.2 节。其他算法可以按照本节规定的策略进行注册。

每个算法都有一个状态字段,用于帮助实现者在选择时参考。

状态值为 “Active” 的算法适合许多用途,建议应用使用这些算法(RECOMMENDED)。这些算法可在对抗性环境中使用,能在一定程度上抵抗碰撞、第一原像和第二原像攻击。对于对抗性场景,接受的 “Active” 算法选择取决于所需的保护强度。更多考虑见 第 6.6 节

状态值为 “Deprecated” 的算法要么不具备上述属性,要么已知较弱(参见 [NO-MD5][NO-SHA])。这些算法可以用于防止数据损坏,但 MUST NOT 在可能存在对抗的场景中使用,例如用于对完整性字段值进行真实性签名。允许使用这些算法可以帮助某些应用(例如过去使用 [RFC3230]、正在迁移到本规范(参见 附录 E)并且已经有现存计算摘要值集合的应用)避免因使用更安全算法重新计算而造成的不必要的运维负担。但这类应用并不免除本节中的要求。没有此类遗留或历史负担的应用应遵循对“Active”算法的使用建议。

关于算法灵活性的讨论见 第 6.6 节

“Hash Algorithms for HTTP Digest Fields” 注册表的注册请求遵循 Specification Required 策略(参见 [RFC8126] 第 4.6 节)。请求应使用下述模板:

Algorithm Key:
用于 Content-DigestRepr-DigestWant-Content-DigestWant-Repr-Digest 字段 Dictionary 成员键的 Structured Fields 键值。
Status:
算法的状态。选项包括:
"Active":
无已知问题的算法
"Provisional":
未经验证的算法
"Deprecated":
已弃用或不安全的算法
Description:
算法的简短描述。
Reference(s):
指向定义该 Algorithm Key 及算法技术细节的主要文档的指针。

在审查注册请求时,指定专家应关注所请求的状态。状态值应反映标准化状态以及相关利益群体(例如 IETF 或安全相关的标准制定组织)的普遍意见。已知弱、已破坏或实验性算法不应被标注为 “Active”。如果注册请求尝试将此类算法注册为 “Active”,指定专家应建议使用 “Deprecated” 或 “Provisional”。

在审查注册请求时,指定专家不得以其状态为 “Deprecated” 或 “Provisional” 为由拒绝注册请求。

允许请求更新或更改现有注册条目的字段。例如,这可用于在安全环境演变时将算法状态从 “Active” 过渡到 “Deprecated”。


6. 安全注意事项

6.1. HTTP 消息并未完全受保护

本文档指定的数据完整性机制保护 HTTP 表示数据或内容,但并不保护 HTTP 头字段与尾部字段,因而不能防止某些类型的损坏。

完整性字段并非旨在对 HTTP 消息的恶意篡改提供通用保护。在缺乏额外安全机制的情况下,中间路径上的恶意行为者可以移除摘要值或用对操纵后的表示数据或内容重新计算的摘要值替换之。可以通过将本文档描述的机制与其它方法结合(例如传输层安全 TLS 或数字签名,如 HTTP Message Signatures [SIGNATURES])来缓解此类攻击。

6.2. 端到端完整性

完整性字段有助于检测由于实现错误、非预期的“转换代理”(参见 [HTTP] 第 7.7 节)或数据跨越多个跃点或系统边界时的其它操作而导致的表示数据或内容修改。即使只是一个简单的端到端表示数据完整性机制也很有价值,因为用户代理可以在将数据交给 HTML 解析器、视频播放器等之前验证资源检索是否成功。

注意,仅使用这些机制并不能在多跃点场景下提供 HTTP 消息的端到端完整性,因为元数据在任何阶段都可能被篡改。保护元数据的方法见 第 6.3 节

6.3. 在签名中的使用

数字签名通常与校验和值一起使用,以确定消息来源的某些标识(参见 [FIPS186-5])。此类签名可以保护一个或多个 HTTP 字段,但当完整性字段被包含在保护范围内时,需要考虑额外事项。

完整性字段的使用对数字签名的类型或格式没有限制。一种可行的方法是将其与 HTTP Message Signatures [SIGNATURES] 结合使用。

摘要明确依赖于“表示元数据”(例如 Content-TypeContent-Encoding 等字段的值)。如果签名保护了完整性字段但未保护其它“表示元数据”,则会使通信暴露于篡改风险。例如,行为者可以操纵 Content-Type 字段值,导致接收方的摘要校验失败,从而阻止应用访问该表示。此类攻击会消耗双方的资源。另见 第 3.2 节

在应用完整性字段时,签名很可能被视为一种对抗性场景;参见 第 5 节Repr-Digest 在与签名结合时提供了有趣的可能性。例如,当没有内容要发送时,可以在消息中包含对空字符串的摘要;如果对该摘要进行签名,接收方可以检测到意外或恶意地添加了内容。反过来,包含并签署用于内容的完整性字段也可以帮助接收方检测内容被移除的位置。

对完整性字段的任何篡改都可能影响签名验证。此类篡改的例子包括对摘要去重或合并不同字段值(参见 [HTTP] 第 5.2 节)。

6.4. 在尾部字段中的使用

在将完整性字段放入尾部(trailer)节之前,发送方应考虑中间体明确被允许丢弃任何尾部(参见 [HTTP] 第 6.5.2 节)。

当完整性字段位于尾部节时,这些字段的值在内容之后才到达。若在收到尾部节之前急于处理内容,则会阻止摘要验证,从而可能导致处理无效数据。

在尾部节中使用完整性字段的好处之一是允许在发送过程中对字节进行哈希。然而,也可能设计出需要以特定方式处理内容的哈希算法,从而抵消这些好处。例如,Merkle Integrity Content Encoding [MICE] 需要以反向顺序处理内容,这意味着必须拥有完整数据,因此在头部或尾部发送完整性字段在处理上几乎没有差别。

6.5. 内容编码内的变化

内容编码机制可能支持不同的编码参数,这意味着相同的输入内容可以产生不同的输出。例如,GZIP 支持多种压缩级别。这类编码参数通常不会作为表示元数据进行传达。例如,不同的压缩级别仍然使用相同的 "Content-Encoding: gzip" 字段。另一个例子是依赖随机数或时间戳的编码,例如 [RFC8188] 中定义的 aes128gcm 内容编码。

由于内容编码内可能存在变动,完整性字段传达的校验和不能在“静态存储”场景中作为完整性证明,除非整个内容被持久化保存。

6.6. 算法灵活性

哈希算法的安全属性并非固定不变。算法灵活性(参见 [RFC7696])通过允许实现从 IANA 的 “Hash Algorithms for HTTP Digest Fields” 注册表中选择哈希算法来实现;参见 第 7.2 节

通过 Want-Content-DigestWant-Repr-Digest(参见 第 4 节)协商哈希算法,或通过发送多个摘要由接收方选择,支持从弱算法过渡到更强算法。依赖某个摘要来实现安全性的接收方将易受其愿意接受的最弱算法的攻击。端点应注意,发送多个值会消耗资源,如果接收方忽略这些值则可能被浪费(参见 第 3 节)。

尽管算法灵活性允许向更强算法迁移,但它不能阻止弱算法的使用。完整性字段并不对哈希算法的降级或替换攻击提供任何缓解措施(参见 [RFC6211] 第 1 节)。为防止此类攻击,端点可以将其支持的算法集合限制为更强的算法,并通过使用 TLS 和/或数字签名来保护字段值。

6.7. 资源耗尽

验证完整性字段会消耗计算资源。为避免资源耗尽,实现在验证时可以限制算法类型、验证次数或内容大小。在这些情况下,完全跳过验证或忽略更高优先级算法的验证失败会留下降级攻击的可能性(参见 第 6.6 节)。


7. IANA 注意事项

7.1. HTTP 字段名注册

IANA 已更新 “Hypertext Transfer Protocol (HTTP) Field Name Registry” [HTTP],如下表所示:

表 1:Hypertext Transfer Protocol (HTTP) 字段名注册表更新
字段名 状态 参考
Content-Digest permanent 第 2 节(RFC 9530)
Repr-Digest permanent 第 3 节(RFC 9530)
Want-Content-Digest permanent 第 4 节(RFC 9530)
Want-Repr-Digest permanent 第 4 节(RFC 9530)
Digest obsoleted [RFC3230],见本规范 第 1.3 节
Want-Digest obsoleted [RFC3230],见本规范 第 1.3 节

7.2. 创建 “Hash Algorithms for HTTP Digest Fields” 注册表

IANA 已在 <https://www.iana.org/assignments/http-digest-hash-al/> 创建了新的 “Hash Algorithms for HTTP Digest Fields” 注册表,并用表 表 2 中的条目填充了该注册表。新注册的流程见 第 5 节

表 2:初始哈希算法
Algorithm Key Status Description Reference
sha-512 Active SHA-512 算法。 [RFC6234], [RFC4648], RFC 9530
sha-256 Active SHA-256 算法。 [RFC6234], [RFC4648], RFC 9530
md5 Deprecated MD5 算法。易受碰撞攻击;参见 [NO-MD5][CMU-836068] [RFC1321], [RFC4648], RFC 9530
sha Deprecated SHA-1 算法。易受碰撞攻击;参见 [NO-SHA][IACR-2020-014] [RFC3174], [RFC4648], [RFC6234], RFC 9530
unixsum Deprecated UNIX "sum" 命令使用的算法。 [RFC4648], [RFC6234], [UNIX], RFC 9530
unixcksum Deprecated UNIX "cksum" 命令使用的算法。 [RFC4648], [RFC6234], [UNIX], RFC 9530
adler Deprecated ADLER32 算法。 [RFC1950], RFC 9530
crc32c Deprecated CRC32c 算法。 [RFC9260] 附录 A, RFC 9530

7.3. 弃用 “Hypertext Transfer Protocol (HTTP) Digest Algorithm Values” 注册表

IANA 已弃用位于 <https://www.iana.org/assignments/http-dig-alg/> 的 “Hypertext Transfer Protocol (HTTP) Digest Algorithm Values” 注册表,并将该注册表上的说明替换为如下文本:

该注册表已被弃用,因为它列出了可用于 DigestWant-Digest 字段的算法,而这些字段由 [RFC3230] 定义,且该 RFC 已被 RFC 9530 废弃。虽然注册并未关闭,但鼓励新的注册使用 “Hash Algorithms for HTTP Digest Fields” 注册表。

8. 参考文献

8.1. 规范性参考文献

[FOLDING]
Watsen, K., Auerswald, E., Farrel, A., 和 Q. Wu,“在 Internet-Drafts 和 RFC 内容中处理长行”,RFC 8792,DOI 10.17487/RFC8792,2020 年 6 月,<https://www.rfc-editor.org/info/rfc8792>。
[HTTP]
Fielding, R., Ed., Nottingham, M., Ed., 和 J. Reschke, Ed., “HTTP 语义”,STD 97, RFC 9110, DOI 10.17487/RFC9110, 2022 年 6 月,<https://www.rfc-editor.org/info/rfc9110>。
[RFC1321]
Rivest, R., “MD5 消息摘要算法”,RFC 1321,DOI 10.17487/RFC1321, 1992 年 4 月,<https://www.rfc-editor.org/info/rfc1321>。
[RFC1950]
Deutsch, P. 和 J-L. Gailly,“ZLIB 压缩数据格式规范 3.3 版本”,RFC 1950,DOI 10.17487/RFC1950, 1996 年 5 月,<https://www.rfc-editor.org/info/rfc1950>。
[RFC2119]
Bradner, S., “在 RFC 中用于指示要求级别的关键字”,BCP 14, RFC 2119, DOI 10.17487/RFC2119, 1997 年 3 月,<https://www.rfc-editor.org/info/rfc2119>。
[RFC3174]
Eastlake 3rd, D. 和 P. Jones,“美国安全哈希算法 1 (SHA1)”,RFC 3174,DOI 10.17487/RFC3174, 2001 年 9 月,<https://www.rfc-editor.org/info/rfc3174>。
[RFC4648]
Josefsson, S., “Base16、Base32 与 Base64 数据编码”,RFC 4648,DOI 10.17487/RFC4648, 2006 年 10 月,<https://www.rfc-editor.org/info/rfc4648>。
[RFC5234]
Crocker, D., Ed. 和 P. Overell, “语法规范的增强 BNF:ABNF”,STD 68, RFC 5234, DOI 10.17487/RFC5234, 2008 年 1 月,<https://www.rfc-editor.org/info/rfc5234>。
[RFC6234]
Eastlake 3rd, D. 和 T. Hansen,“美国安全哈希算法(SHA 及基于 SHA 的 HMAC 与 HKDF)”,RFC 6234,DOI 10.17487/RFC6234, 2011 年 5 月,<https://www.rfc-editor.org/info/rfc6234>。
[RFC7405]
Kyzivat, P., “ABNF 中的区分大小写字符串支持”,RFC 7405,DOI 10.17487/RFC7405, 2014 年 12 月,<https://www.rfc-editor.org/info/rfc7405>。
[RFC8126]
Cotton, M., Leiba, B., 和 T. Narten, “在 RFC 中撰写 IANA 注意事项章节的指南”,BCP 26, RFC 8126, DOI 10.17487/RFC8126, 2017 年 6 月,<https://www.rfc-editor.org/info/rfc8126>。
[RFC8174]
Leiba, B., “RFC 2119 关键字中大写与小写的歧义”,BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2017 年 5 月,<https://www.rfc-editor.org/info/rfc8174>。
[STRUCTURED-FIELDS]
Nottingham, M. 和 P-H. Kamp, “HTTP 的结构化字段值”,RFC 8941,DOI 10.17487/RFC8941, 2021 年 2 月,<https://www.rfc-editor.org/info/rfc8941>。

8.2. 信息性参考文献

[CMU-836068]
Carnegie Mellon University, Software Engineering Institute, “MD5 易受碰撞攻击”, 2008 年 12 月,<https://www.kb.cert.org/vuls/id/836068/>。
[FIPS186-5]
美国国家标准与技术研究院 (NIST), “数字签名标准 (DSS)”, FIPS PUB 186-5, DOI 10.6028/NIST.FIPS.186-5, 2023 年 2 月, <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf>。
[HTTP/1.1]
Fielding, R., Ed., Nottingham, M., Ed., 和 J. Reschke, Ed., “HTTP/1.1”, STD 99, RFC 9112, DOI 10.17487/RFC9112, 2022 年 6 月,<https://www.rfc-editor.org/info/rfc9112>。
[IACR-2020-014]
Leurent, G. 和 T. Peyrin, “SHA-1 已成废墟”, 2020 年 1 月, <https://eprint.iacr.org/2020/014.pdf>。
[MICE]
Thomson, M. 和 J. Yasskin, “Merkle 完整性内容编码”, 工作进行中, draft-thomson-http-mice-03, 工作进行中, 2018 年 8 月, <https://datatracker.ietf.org/doc/html/draft-thomson-http-mice-03>。
[NO-MD5]
Turner, S. 和 L. Chen, “针对 MD5 消息摘要与 HMAC-MD5 算法的更新安全注意事项”, RFC 6151, DOI 10.17487/RFC6151, 2011 年 3 月, <https://www.rfc-editor.org/info/rfc6151>。
[NO-SHA]
Polk, T., Chen, L., Turner, S., 和 P. Hoffman, “SHA-0 与 SHA-1 消息摘要算法的安全注意事项”, RFC 6194, DOI 10.17487/RFC6194, 2011 年 3 月, <https://www.rfc-editor.org/info/rfc6194>。
[PATCH]
Dusseault, L. 和 J. Snell, “HTTP 的 PATCH 方法”, RFC 5789, DOI 10.17487/RFC5789, 2010 年 3 月, <https://www.rfc-editor.org/info/rfc5789>。
[RFC3230]
Mogul, J. 和 A. Van Hoff, “HTTP 中的实例摘要”, RFC 3230, DOI 10.17487/RFC3230, 2002 年 1 月, <https://www.rfc-editor.org/info/rfc3230>。
[RFC6211]
Schaad, J., “加密消息语法 (CMS) 算法标识符保护属性”, RFC 6211, DOI 10.17487/RFC6211, 2011 年 4 月, <https://www.rfc-editor.org/info/rfc6211>。
[RFC7396]
Hoffman, P. 和 J. Snell, “JSON 合并补丁”, RFC 7396, DOI 10.17487/RFC7396, 2014 年 10 月, <https://www.rfc-editor.org/info/rfc7396>。
[RFC7696]
Housley, R., “密码算法灵活性与强制实现算法选择的指南”, BCP 201, RFC 7696, DOI 10.17487/RFC7696, 2015 年 11 月, <https://www.rfc-editor.org/info/rfc7696>。
[RFC8188]
Thomson, M., “用于 HTTP 的加密内容编码”, RFC 8188, DOI 10.17487/RFC8188, 2017 年 6 月, <https://www.rfc-editor.org/info/rfc8188>。
[RFC9260]
Stewart, R., Tüxen, M., 和 K. Nielsen, “流控制传输协议”, RFC 9260, DOI 10.17487/RFC9260, 2022 年 6 月, <https://www.rfc-editor.org/info/rfc9260>。
[RFC9457]
Nottingham, M., Wilde, E., 和 S. Dalal, “HTTP API 的问题详细信息”, RFC 9457, DOI 10.17487/RFC9457, 2023 年 7 月, <https://www.rfc-editor.org/info/rfc9457>。
[SIGNATURES]
Backman, A., Ed., Richer, J., Ed., 和 M. Sporny, “HTTP 消息签名”, RFC 9421, DOI 10.17487/RFC9421, 2024 年 2 月, <https://www.rfc-editor.org/info/rfc9421>。
[TLS]
Rescorla, E., “传输层安全 (TLS) 协议 第 1.3 版”, RFC 8446, DOI 10.17487/RFC8446, 2018 年 8 月, <https://www.rfc-editor.org/info/rfc8446>。
[UNIX]
The Open Group, “The Single UNIX Specification, Version 2 - 6 Vol Set for UNIX 98”, 1998 年 1 月。

附录 A. 资源表示与表示数据

下面的示例展示了表示元数据、内容转换和方法如何影响消息与内容。这些示例并非穷尽所有情况。

除非另有说明,示例均基于 JSON 对象 {"hello": "world"} 后跟一个 LF。当内容包含不可打印字符(例如经编码时),将以十六进制编码字节序列显示。

设想客户端希望使用 PUT 方法上载一个 JSON 对象。它可以使用 application/json 的 Content-Type 且不使用任何内容编码来完成此操作。

PUT /entries/1234 HTTP/1.1
Host: foo.example
Content-Type: application/json
Content-Length: 19

{"hello": "world"}

图 1:包含 JSON 对象且无任何内容编码的请求

然而,使用内容编码颇为常见。客户端也可以用 GZIP 编码上载相同的数据(参见 [HTTP] 第 8.4.1.3 节)。 注意,在这种情况下,由于编码开销,Content-Length 的值会更大。

PUT /entries/1234 HTTP/1.1
Host: foo.example
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 39

1F 8B 08 00 88 41 37 64 00 FF
AB 56 CA 48 CD C9 C9 57 B2 52
50 2A CF 2F CA 49 51 AA E5 02
00 D9 E4 31 E7 13 00 00 00

图 2:包含 GZIP 编码 JSON 对象的请求

在未通过 Content-Encoding 指示的情况下发送 GZIP 编码的数据意味着内容格式错误。在此情形下,服务器可以返回错误响应。

PUT /entries/1234 HTTP/1.1
Host: foo.example
Content-Type: application/json

Content-Length: 39

1F 8B 08 00 88 41 37 64 00 FF
AB 56 CA 48 CD C9 C9 57 B2 52
50 2A CF 2F CA 49 51 AA E5 02
00 D9 E4 31 E7 13 00 00 00

图 3:包含格式错误 JSON 的请求

HTTP/1.1 400 Bad Request

图 4:针对格式错误内容的错误响应

范围请求会影响传输的消息内容。在此示例中,客户端访问位于 /entries/1234 的资源,该资源为 JSON 对象 {"hello": "world"} 后跟一个 LF。然而,客户端指示了首选的内容编码及特定的字节范围。

GET /entries/1234 HTTP/1.1
Host: foo.example
Accept-Encoding: gzip
Range: bytes=1-7

图 5:请求部分内容

服务器通过返回部分表示满足客户端请求(等价于图 2 中完整 JSON 对象的前 10 个字节)。

HTTP/1.1 206 Partial Content
Content-Encoding: gzip
Content-Type: application/json
Content-Range: bytes 0-9/39

1F 8B 08 00 A5 B4 BD 62 02 FF

图 6:来自 GZIP 编码表示的部分响应

除了内容编码或范围请求外,HTTP 方法也会影响传输的消息内容。例如,HEAD 请求的响应不携带内容,但此示例中仍包含 Content-Length;见 [HTTP] 第 8.6 节

HEAD /entries/1234 HTTP/1.1
Host: foo.example
Accept: application/json
Accept-Encoding: gzip

图 7:HEAD 请求

HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 39

图 8:对 HEAD 请求的响应(空内容)

最后,响应的语义可能使目标 URI 与所封装的表示解耦。在下面的示例中,客户端向 /authors/ 发出 POST 请求,但响应包含一个 Content-Location 头字段,指示所封装的表示对应于位于 /authors/123 的资源。注意此示例中未发送 Content-Length

POST /authors/ HTTP/1.1
Host: foo.example
Accept: application/json
Content-Type: application/json

{"author": "Camilleri"}

图 9:POST 请求

HTTP/1.1 201 Created
Content-Type: application/json
Content-Location: /authors/123
Location: /authors/123

{"id": "123", "author": "Camilleri"}

图 10:包含 Content-Location 头字段的响应


附录 B. 未经请求的 Digest 示例

下面的示例演示了服务器在客户端未使用 Want-Content-DigestWant-Repr-Digest 请求的情况下返回 Content-DigestRepr-Digest 字段的交互场景。

某些示例在内容中包含 JSON 对象。为便于展示,那些能完全符合行长限制的对象以单行紧凑表示且不包含前导空格;超出行长限制的对象将按每个键值对一行并带两个空格前导缩进的形式展示。

本文档中定义的校验和机制与媒体类型无关,并不为特定格式提供规范化算法。示例中的计算包含任何空格。尽管示例可以同时包含两个字段,Content-DigestRepr-Digest 也可以单独返回。

B.1. 服务器返回完整表示数据

在此示例中,消息内容传达了完整的表示数据。这意味着在响应中,Content-DigestRepr-Digest 都是对 JSON 对象 {"hello": "world"} 后跟一个 LF 计算得到的;因此它们具有相同的值。

GET /items/123 HTTP/1.1
Host: foo.example

图 11:获取某项的 GET 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 19
Content-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:

{"hello": "world"}

图 12:具有相同 Repr-DigestContent-Digest 的响应

B.2. 服务器不返回表示数据

在此示例中,使用 HEAD 请求来检索资源的校验和。

响应中的 Content-Digest 字段值是对空内容计算的。Repr-Digest 是对 JSON 对象 {"hello": "world"} 后跟一个 LF 计算的,但由于没有内容该对象不显示出来。

HEAD /items/123 HTTP/1.1
Host: foo.example

图 13:获取某项的 HEAD 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Content-Digest: \
  sha-256=:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=:
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:

图 14:同时包含 Content-DigestDigest(空内容)的响应

B.3. 服务器返回部分表示数据

在此示例中,客户端发出范围请求,服务器以部分内容响应。

GET /items/123 HTTP/1.1
Host: foo.example
Range: bytes=10-18

图 15:请求部分内容

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 206 Partial Content
Content-Type: application/json
Content-Range: bytes 10-18/19
Content-Digest: \
  sha-256=:jjcgBDWNAtbYUXI37CVG3gRuGOAjaaDRGpIUFsdyepQ=:
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:

"world"}

图 16:同时具有 Content-DigestRepr-Digest 的部分响应

在上述响应消息中,请注意 Repr-DigestContent-Digests 不同。Repr-Digest 字段值是在整个 JSON 对象 {"hello": "world"} 后跟一个 LF 上计算的,字段如下所示:

NOTE: '\' line wrapping per RFC 8792

Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:

然而,由于消息内容受限为字节 10-18,Content-Digest 字段值是在序列 "world"} 后跟一个 LF 上计算的,因此产生如下结果:

NOTE: '\' line wrapping per RFC 8792

Content-Digest: \
  sha-256=:jjcgBDWNAtbYUXI37CVG3gRuGOAjaaDRGpIUFsdyepQ=:

B.4. 客户端与服务器提供完整表示数据

请求包含一个在所封装表示上计算的 Repr-Digest 字段值。它还包含一个声明客户端支持 Brotli 编码的 Accept-Encoding: br 头字段。

响应包含一个指示所选表示为 Brotli 编码的 Content-Encoding: br。因此响应中的 Repr-Digest 字段值与请求中不同。

出于展示目的,响应体以十六进制编码字节序列显示,因为其中包含不可打印字符。

NOTE: '\' line wrapping per RFC 8792

PUT /items/123 HTTP/1.1
Host: foo.example
Content-Type: application/json
Accept-Encoding: br
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:

{"hello": "world"}

图 17:带有 Digest 的 PUT 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /items/123
Content-Encoding: br
Content-Length: 23
Repr-Digest: \
  sha-256=:d435Qo+nKZ+gLcUHn7GQtQ72hiBVAgqoLsZnZPiTGPk=:

8B 08 80 7B 22 68 65 6C 6C 6F
22 3A 20 22 77 6F 72 6C 64 22
7D 0A 03

图 18:包含已编码响应摘要的响应

B.5. 客户端提供完整表示数据且服务器不提供表示数据

请求中的 Repr-Digest 字段值是在所封装内容上计算的,该内容为 JSON 对象 {"hello": "world"} 后跟一个 LF。

响应中的 Repr-Digest 字段值取决于表示元数据头字段,包括 Content-Encoding: br,即使响应不包含内容亦然。

NOTE: '\' line wrapping per RFC 8792

PUT /items/123 HTTP/1.1
Host: foo.example
Content-Type: application/json
Content-Length: 19
Accept-Encoding: br
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg==:

{"hello": "world"}
HTTP/1.1 204 No Content
Content-Type: application/json
Content-Encoding: br
Repr-Digest: sha-256=:d435Qo+nKZ+gLcUHn7GQtQ72hiBVAgqoLsZnZPiTGPk=:

图 19:带有 Digest 的空响应

B.6. 客户端与服务器提供完整表示数据

响应包含使用不同算法的两个摘要值。

出于展示目的,响应体以十六进制编码字节序列显示,因为其中包含不可打印字符。

NOTE: '\' line wrapping per RFC 8792

PUT /items/123 HTTP/1.1
Host: foo.example
Content-Type: application/json
Accept-Encoding: br
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg==:

{"hello": "world"}

图 20:带有 Digest 的 PUT 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: br
Content-Location: /items/123
Repr-Digest: \
  sha-256=:d435Qo+nKZ+gLcUHn7GQtQ72hiBVAgqoLsZnZPiTGPk=:,\
  sha-512=:db7fdBbgZMgX1Wb2MjA8zZj+rSNgfmDCEEXM8qLWfpfoNY0sCpHAzZbj\
  09X1/7HAb7Od5Qfto4QpuBsFbUO3dQ==:

8B 08 80 7B 22 68 65 6C 6C 6F
22 3A 20 22 77 6F 72 6C 64 22
7D 0A 03

图 21:对已编码内容的响应摘要

B.7. POST 响应未引用请求 URI

请求中的 Repr-Digest 字段值是在所封装的表示上计算的(见 第 3.1 节),该表示为 JSON 对象 {"title": "New Title"} 后跟一个 LF。

响应中封装的表示是一个多行 JSON 对象后跟一个 LF。它通过 Content-Location 指向由其值标识的资源(参见 [HTTP] 第 6.4.2 节);因此应用可以将 Repr-Digest 与由 Content-Location 引用的资源关联使用。

POST /books HTTP/1.1
Host: foo.example
Content-Type: application/json
Accept: application/json
Accept-Encoding: identity
Repr-Digest: sha-256=:mEkdbO7Srd9LIOegftO0aBX+VPTVz7/CSHes2Z27gc4=:

{"title": "New Title"}

图 22:带有 Digest 的 POST 请求

HTTP/1.1 201 Created
Content-Type: application/json
Content-Location: /books/123
Location: /books/123
Repr-Digest: sha-256=:uVSlinTTdQUwm2On4k8TJUikGN1bf/Ds8WPX4oe0h9I=:

{
  "id": "123",
  "title": "New Title"
}

图 23:包含资源摘要的响应

B.8. POST 响应描述请求状态

请求中的 Repr-Digest 字段值是在所封装的表示上计算的(见 第 3.1 节),该表示为 JSON 对象 {"title": "New Title"} 后跟一个 LF。

响应中封装的表示描述了请求的状态,因此 Repr-Digest 在该封装表示上计算。它为一个多行 JSON 对象后跟一个 LF。

响应的 Repr-Digest 与由 Location 引用的资源之间没有明确关联。

POST /books HTTP/1.1
Host: foo.example
Content-Type: application/json
Accept: application/json
Accept-Encoding: identity
Repr-Digest: sha-256=:mEkdbO7Srd9LIOegftO0aBX+VPTVz7/CSHes2Z27gc4=:

{"title": "New Title"}

图 24:带有 Digest 的 POST 请求

HTTP/1.1 201 Created
Content-Type: application/json
Repr-Digest: sha-256=:yXIGDTN5VrfoyisKlXgRKUHHMs35SNtyC3szSz1dbO8=:
Location: /books/123

{
  "status": "created",
  "id": "123",
  "ts": 1569327729,
  "instance": "/books/123"
}

图 25:包含表示摘要的响应

B.9. Digest 与 PATCH

此情形类似于目标资源反映目标 URI 的 POST 请求。

PATCH 请求使用 application/merge-patch+json 媒体类型(参见 [RFC7396])。Repr-Digest 在对应补丁文档的内容上计算,该内容为 JSON 对象 {"title": "New Title"} 后跟一个 LF。

响应中的 Repr-Digest 字段值是在被修补资源的完整表示上计算的。它为一个多行 JSON 对象后跟一个 LF。

PATCH /books/123 HTTP/1.1
Host: foo.example
Content-Type: application/merge-patch+json
Accept: application/json
Accept-Encoding: identity
Repr-Digest: sha-256=:mEkdbO7Srd9LIOegftO0aBX+VPTVz7/CSHes2Z27gc4=:

{"title": "New Title"}

图 26:带有 Digest 的 PATCH 请求

HTTP/1.1 200 OK
Content-Type: application/json
Repr-Digest: sha-256=:uVSlinTTdQUwm2On4k8TJUikGN1bf/Ds8WPX4oe0h9I=:

{
  "id": "123",
  "title": "New Title"
}

图 27:包含表示摘要的响应

注意,不带内容但具有相同 Repr-Digest 字段值的 204 No Content 响应也同样是合法的。在那种情况下,Content-Digest 会在空内容上计算。

B.10. 错误响应

在错误响应中,表示数据不必指向目标资源,而是指向错误的表示。

在下面的示例中,客户端向图 26(参见 PATCH 请求)中相同的请求对 /books/123 发出补丁请求。然而,该资源不存在,服务器生成了一个 404 响应,响应体按照 [RFC9457] 描述了错误。

响应中的 Repr-Digest 字段值是在此封装表示上计算的。它为一个多行 JSON 对象后跟一个 LF。

HTTP/1.1 404 Not Found
Content-Type: application/problem+json
Repr-Digest: sha-256=:EXB0S2VF2H7ijkAVJkH1Sm0pBho0iDZcvVUHHXTTZSA=:

{
  "title": "Not Found",
  "detail": "Cannot PATCH a non-existent resource",
  "status": 404
}

图 28:包含错误表示摘要的响应

B.11. 与尾部字段和传输编码一起使用

源服务器将 Repr-Digest 作为尾部字段发送,以便在流式传输内容时计算摘要值,从而减轻资源消耗。由于 Repr-Digest 设计为独立于一次或多次传输编码的使用(参见 第 3 节),因此其字段值与附录 B.1 中相同。

在下面的响应内容中,字符串 "\r\n" 表示 CRLF 字节。

GET /items/123 HTTP/1.1
Host: foo.example

图 29:GET 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Trailer: Repr-Digest

8\r\n
{"hello"\r\n
8\r\n
: "world\r\n
3\r\n
"}\n\r\n
0\r\n
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg==:\r\n

图 30:带有 Digest 的分块响应


Appendix C. 示例:Want-Repr-Digest 请求的 Digest

下面的示例演示了客户端使用 Want-Repr-Digest 请求 Repr-Digest 的交互场景。Content-DigestWant-Content-Digest 的行为相同。

某些示例在内容中包含 JSON 对象。为便于展示,能够完全符合行长限制的对象以单行紧凑表示且不包含前导空格;超出行长限制的对象将按每个键值对一行并带两个空格前导缩进的形式展示。

本文档中描述的校验和机制与媒体类型无关,并不为特定格式提供规范化算法。示例的计算包含任何空格。

C.1. 服务器选择客户端最不偏好的算法

客户端请求摘要并偏好 "sha"。服务器仍然可以自由地用 "sha-256" 作出响应。

GET /items/123 HTTP/1.1
Host: foo.example
Want-Repr-Digest: sha-256=3, sha=10

图 31:带有 Want-Repr-Digest 的 GET 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Repr-Digest: \
  sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg==:

{"hello": "world"}

图 32:使用不同算法的响应

C.2. 服务器选择客户端不支持的算法

客户端请求 "sha" 摘要,因为那是它唯一支持的算法。服务器没有义务生成包含 "sha" 摘要的响应;它可以改用不同的算法。

GET /items/123 HTTP/1.1
Host: foo.example
Want-Repr-Digest: sha=10

图 33:带有 Want-Repr-Digest 的 GET 请求

NOTE: '\' line wrapping per RFC 8792

HTTP/1.1 200 OK
Content-Type: application/json
Repr-Digest: \
  sha-512=:YMAam51Jz/jOATT6/zvHrLVgOYTGFy1d6GJiOHTohq4yP+pgk4vf2aCs\
  yRZOtw8MjkM7iw7yZ/WkppmM44T3qg==:

{"hello": "world"}

图 34:使用客户端不支持算法的响应

C.3. 服务器不支持客户端算法并返回错误

附录 C.2 是一个示例,展示了服务器忽略客户端首选摘要算法的情形。作为替代,服务器也可以拒绝该请求并返回包含 4xx 或 5xx 等错误状态码的响应。本规范未对状态码选择提出强制性要求;下面的示例只是说明一种可选方案。

在此示例中,客户端请求 "sha" Repr-Digest,服务器返回包含问题详细信息(参见 [RFC9457])的错误响应体。问题详细信息列出了服务器支持的哈希算法。这仅为示例;本规范未定义此类内容的格式或要求。

GET /items/123 HTTP/1.1
Host: foo.example
Want-Repr-Digest: sha=10

图 35:带有 Want-Repr-Digest 的 GET 请求

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{
  "title": "Bad Request",
  "detail": "Supported hashing algorithms: sha-256, sha-512",
  "status": 400
}

图 36:响应中通告支持的算法


Appendix D. 示例 Digest

本节展示针对不同哈希算法的摘要值示例。输入值为 JSON 对象 {"hello": "world"}。摘要值是对该输入运行相关哈希算法得到输出字节,然后将输出字节通过 Byte Sequence 序列化处理得到的;参见 [STRUCTURED-FIELDS] 第 4.1.8 节

NOTE: '\' line wrapping per RFC 8792

sha-512 -   :WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+TaPm+\
            AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==:

sha-256 -   :X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:

md5 -       :Sd/dVLAcvNLSq16eXua5uQ==:

sha -       :07CavjDP4u3/TungoUHJO/Wzr4c=:

unixsum -   :GQU=:

unixcksum - :7zsHAA==:

adler -     :OZkGFw==:

crc32c -    :Q3lHIA==:

Appendix E. 从 RFC 3230 迁移

HTTP 摘要是通过对输入数据应用哈希算法计算得到的。[RFC3230] 将输入数据定义为“instance”(实例),并对其进行了定义。该“instance”概念现已被 HTTP 语义中的“representation”所取代。已知一些实现将 [RFC3230] 中的 “instance” 误解为 HTTP 内容。将内容用于 Digest 字段是一个错误,会导致遵从 [RFC3230] 的对等方之间发生互操作性问题。

[RFC3230] 原本仅打算使用 HTTP 现在定义为选定表示数据的内容。Repr-Digest 字段的定义中(参见 第 3 节)对摘要与表示的语义概念进行了说明。

尽管 DigestRepr-Digest 的语法不同,但本文件对 Repr-Digest 给出的考虑与示例同样适用于 Digest,因为它们作用于相同的输入数据;参见第 3.1 节、第 6 节 与第 6.3 节

[RFC3230] 从未能够在 Digest 字段中传达 HTTP 消息内容的摘要;而 Content-Digest 现在提供了该功能。

[RFC3230] 允许算法定义其用于 Digest 字段的输出编码格式,结果出现了 base64、十六进制或十进制等混合格式。通过使用 Structured Fields,Content-DigestRepr-Digest 仅使用单一编码格式。附录 D(示例摘要值)中提供了进一步说明与示例。


致谢

本文档基于 [RFC3230] 的思想,因此感谢 Jeff Mogul 与 Arthur Van Hoff 的卓越工作。将 [RFC3230] 刷新为现规范的初衷源于与 Mark Nottingham、Jeffrey Yasskin 和 Martin Thomson 在审查 MICE 内容编码时的讨论。

感谢 Julian Reschke 对本文档的宝贵贡献,以及以下通过报告错误、提出建设性问题、起草或审阅文本并评估未决问题来改进本规范的贡献者:Mike Bishop、Brian Campbell、Matthew Kerwin、James Manger、Tommy Pauly、Sean Turner、Justin Richer 与 Erik Wilde。


作者联系信息

Roberto Polli
Team Digitale, Italian Government
Italy
EMail: robipolli@gmail.com
Lucas Pardue
Cloudflare
EMail: lucas@lucaspardue.com