3.7 Computing the Message Hashes (计算消息哈希)
3.7. Computing the Message Hashes (计算消息哈希)
签名和验证消息签名都从计算消息的两个加密哈希开始。Signer 将选择 "Signer Actions" (Section 5) 中描述的签名参数; Verifier 将使用正在验证的 DKIM-Signature 头字段中指定的参数。在以下讨论中, 使用 DKIM-Signature 头字段中存在 (验证时) 或将被创建 (签名时) 的标签名称。请注意, 规范化 (Section 3.4) 仅用于准备要签名或验证的电子邮件; 它不会以任何方式影响传输的电子邮件。
Signer/Verifier 必须计算两个哈希: 一个对消息正文进行哈希, 另一个对消息的选定头字段进行哈希。
Signer 必须按所示顺序计算它们。Verifier 可以按对 Verifier 方便的任何顺序计算它们, 前提是结果在语义上与按此顺序计算时的语义相同。
在哈希步骤 1 中, Signer/Verifier 必须对消息正文进行哈希, 使用 "c=" 标签中指定的正文规范化算法进行规范化, 然后截断到 "l=" 标签中指定的长度。然后将该哈希值转换为 base64 形式, 并插入 (Signer) 或与 (Verifier) DKIM-Signature 头字段的 "bh=" 标签进行比较。
在哈希步骤 2 中, Signer/Verifier 必须按指示的顺序将以下内容传递给哈希算法。
-
由 "h=" 标签指定的头字段, 按该标签中指定的顺序, 并使用 "c=" 标签中指定的头规范化算法进行规范化。每个头字段必须以单个 CRLF 终止。
-
在消息中存在 (验证) 或将被插入 (签名) 的 DKIM-Signature 头字段, 其中 "b=" 标签的值 (包括所有周围的空白) 已删除 (即, 视为空字符串), 使用 "c=" 标签中指定的头规范化算法进行规范化, 并且没有尾随 CRLF。
DKIM-Signature 头字段中的所有标签及其值都包含在加密哈希中, 唯一的例外是 "b=" (签名) 标签的值部分, 该部分必须被视为空字符串。所有标签都必须被包括, 即使 Verifier 可能不理解它们。头字段必须在消息正文之后而不是与其余头字段一起呈现给哈希算法, 并且必须按 "c=" (规范化) 标签中指定的方式进行规范化。DKIM-Signature 头字段必须不包含在其自己的 "h=" 标签中, 尽管可以签名其他 DKIM-Signature 头字段 (参见 Section 4)。
当计算将使用 base64 或 quoted-printable 编码传输的消息的哈希时, Signer 必须在编码后计算哈希。同样, Verifier 必须在解码 base64 或 quoted-printable 文本之前将值纳入哈希。但是, 哈希必须在传输级编码 (例如 SMTP "dot-stuffing" (对以 "." 开头的行进行修改以避免与 SMTP 消息结束标记混淆, 如 [RFC5321] 中所指定)) 之前计算。
除了 Section 3.4 中描述的规范化过程外, DKIM 签名过程将消息正文视为简单的八位字节字符串。DKIM 消息可以是纯文本或 MIME 格式; 不会对 MIME 内容进行特殊处理。MIME 格式的消息附件必须包含在签名的内容中。
更正式地, 签名算法的伪代码是:
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: 使用 "c" 参数中指定的正文算法生成的正文的规范化表示, 如 Section 3.4 中所定义, 并且排除 DKIM-Signature 字段。
- l-param: "l" 参数的正文长度值。
- data-hash: 使用 hash-alg 算法对头 (包括 DKIM-Signature 头) 和正文哈希进行哈希的输出。
- h-headers: 要签名的头列表, 如 "h" 参数中所指定。
- D-SIG: 规范化的 DKIM-Signature 字段本身, 不包含参数的签名值部分, 即空参数值。
- signature: 由签名算法生成的签名值。
- sig-alg: "a" 参数指定的签名算法。
- d-domain: "d" 参数中指定的域名。
- selector: "s" 参数中指定的 selector 值。
注意: 许多数字签名 API 使用单个 "sign()" 原语提供哈希和 RSA 私钥应用。使用此类 API 时, 算法中的最后两个步骤可能会合并为一个调用, 该调用将同时执行 "a-hash-alg" 和 "sig-alg"。