跳到主要内容

3.7 计算消息哈希

3.7. 计算消息哈希

消息签名的生成和验证都从对消息计算两个加密哈希开始. Signer 会按照 "Signer Actions" (Section 5) 中的描述选择签名参数; Verifier 会使用正在验证的 DKIM-Signature header field 中指定的参数. 以下讨论使用 DKIM-Signature header field 中的 tag 名称, 该 header field 在验证时已经存在, 在签名时将被创建. 注意, 规范化 (Section 3.4) 仅用于为签名或验证准备电子邮件; 它不会以任何方式影响传输中的电子邮件.

Signer/Verifier MUST 计算两个哈希: 一个针对消息正文, 另一个针对消息中选定的 header field.

Signer MUST 按所示顺序计算它们. Verifier MAY 按自身方便的任意顺序计算它们, 前提是结果在语义上与按此顺序计算所得结果相同.

在哈希步骤 1 中, Signer/Verifier MUST 对消息正文进行哈希, 该正文先使用 "c=" tag 中指定的正文规范化算法进行规范化, 然后截断到 "l=" tag 中指定的长度. 随后该哈希值被转换为 base64 形式, 并由 Signer 插入 DKIM-Signature header field 的 "bh=" tag, 或由 Verifier 与该 tag 比较.

在哈希步骤 2 中, Signer/Verifier MUST 按所示顺序把以下内容传递给哈希算法.

  1. "h=" tag 指定的 header field, 按该 tag 中指定的顺序排列, 并使用 "c=" tag 中指定的 header 规范化算法进行规范化. 每个 header field MUST 以单个 CRLF 结束.

  2. 消息中已经存在 (验证时) 或将要插入 (签名时) 的 DKIM-Signature header field, 其中 "b=" tag 的值 (包括其周围所有空白) 已删除 (即视为空字符串), 并使用 "c=" tag 中指定的 header 规范化算法进行规范化, 且末尾不带 CRLF.

DKIM-Signature header field 中的所有 tag 及其值都会包含在加密哈希中, 唯一例外是 "b=" (signature) tag 的值部分, 它 MUST 被视为空字符串. 即使 Verifier 可能不理解某些 tag, 所有 tag 也 MUST 包含在内. 该 header field MUST 在消息正文之后传递给哈希算法, 而不是与其他 header field 一起传递, 并且 MUST 按 "c=" (canonicalization) tag 中指定的方式规范化. DKIM-Signature header field MUST NOT 包含在其自身的 "h=" tag 中, 但其他 DKIM-Signature header field MAY 被签名 (见 Section 4).

当对将使用 base64 或 quoted-printable 编码传输的消息计算哈希时, Signer MUST 在编码之后计算哈希. 同样, Verifier MUST 在解码 base64 或 quoted-printable 文本之前把这些值纳入哈希. 但是, 哈希 MUST 在 SMTP "dot-stuffing" 等传输层编码之前计算; dot-stuffing 是指修改以 "." 开头的行, 以避免与 [RFC5321] 指定的 SMTP 消息结束标记混淆.

除 Section 3.4 中描述的规范化过程外, DKIM 签名过程只是把消息正文视为 octet 字符串. DKIM 消息 MAY 为纯文本格式或 MIME 格式; MIME 内容不会获得特殊处理. MIME 格式的消息附件 MUST 包含在被签名内容中.

更形式化地说, 签名算法的伪代码为:

body-hash    =  hash-alg (canon-body, l-param)
data-hash = hash-alg (h-headers, D-SIG, body-hash)
signature = sig-alg (d-domain, selector, data-hash)

其中:

  • body-hash: 使用 hash-alg 对正文进行哈希所得的输出.
  • hash-alg: "a" 参数指定的哈希算法.
  • canon-body: 正文的规范化表示, 按 Section 3.4 定义使用 "c" 参数指定的正文算法生成, 且不包括 DKIM-Signature 字段.
  • l-param: "l" 参数的正文长度值.
  • data-hash: 使用 hash-alg 算法对 header (包括 DKIM-Signature header) 和正文哈希进行哈希所得的输出.
  • h-headers: "h" 参数指定的待签名 header 列表.
  • D-SIG: 规范化后的 DKIM-Signature 字段本身, 不含参数中的签名值部分, 即参数值为空.
  • signature: 由签名算法生成的签名值.
  • sig-alg: "a" 参数指定的签名算法.
  • d-domain: "d" 参数指定的域名.
  • selector: "s" 参数指定的 selector 值.

NOTE: 许多数字签名 API 使用单个 "sign()" 原语同时提供哈希和 RSA 私钥应用. 使用此类 API 时, 算法的最后两个步骤很可能合并为一次调用, 同时执行 "a-hash-alg" 和 "sig-alg".