跳到主要内容

3.5. DKIM-Signature Header Field

电子邮件签名存储在 DKIM-Signature header field 中. 此 header field 包含全部签名数据和 key 获取数据. DKIM-Signature 值是 Section 3.2 中描述的 tag-list.

DKIM-Signature header field SHOULD 被视为 [RFC5322] Section 3.6 中定义的 trace header field, 因此 SHOULD NOT 被重新排序, 并且 SHOULD 被前置到消息中.

正在创建或验证的 DKIM-Signature header field 始终包含在签名计算中, 位于其余被签名 header field 之后; 但是, 在计算或验证签名时, 该 DKIM-Signature header field 的 "b=" tag 值 (签名值) MUST 被视为空字符串. DKIM-Signature header field 中的未知 tag MUST 包含在签名计算中, 但 Verifier 在其他方面 MUST 忽略它们. 签名中包含的其他 DKIM-Signature header field 应作为普通 header field 处理; 特别是, "b=" tag 不作特殊处理.

每种字段类型的编码如下所列. 描述为 qp-section 的 tag 按 MIME Part One [RFC2045] Section 6.7 中的方式编码, 并额外把分号字符转换为 "=3B"; 直观地说, 这是一行 quoted-printable 编码文本. dkim-quoted-printable 语法在 Section 2.11 中定义.

DKIM-Signature header field 上的 tag 及其类型和要求状态如下所示. 未识别 tag MUST 被忽略.

DKIM-Signature Tags

v= 版本

类型: plain-text; REQUIRED

此 tag 定义适用于该签名 record 的本规范版本. 对于符合此 DKIM 版本的实现, 它 MUST 具有值 "1".

ABNF:

sig-v-tag = %x76 [FWS] "=" [FWS] 1*DIGIT

INFORMATIVE NOTE: 随着本规范新版本发布, DKIM-Signature 版本号可能按算术方式递增.

a= 算法

类型: plain-text; REQUIRED

用于生成签名的算法. Verifier MUST 支持 "rsa-sha1" 和 "rsa-sha256"; Signer SHOULD 使用 "rsa-sha256" 签名. 算法描述见 Section 3.3.

ABNF:

sig-a-tag = %x61 [FWS] "=" [FWS] sig-a-tag-alg
sig-a-tag-alg = sig-a-tag-k "-" sig-a-tag-h
sig-a-tag-k = "rsa" / x-sig-a-tag-k
sig-a-tag-h = "sha1" / "sha256" / x-sig-a-tag-h
x-sig-a-tag-k = ALPHA *(ALPHA / DIGIT) ; for later extension
x-sig-a-tag-h = ALPHA *(ALPHA / DIGIT) ; for later extension

b= 签名数据

类型: base64; REQUIRED

签名数据. 此值中的空白会被忽略, 并且在重组原始签名时 MUST 被忽略. 特别是, 签名过程可以在此值的任意位置安全插入 FWS, 以符合行长限制. 关于签名如何计算, 见 "Signer Actions" (Section 5).

ABNF:

sig-b-tag = %x62 [FWS] "=" [FWS] sig-b-tag-data
sig-b-tag-data = base64string

bh= 正文哈希

类型: base64; REQUIRED

消息规范化正文部分的哈希, 受 "l=" tag 限制. 此值中的空白会被忽略, 并且在重组原始签名时 MUST 被忽略. 特别是, 签名过程可以在此值的任意位置安全插入 FWS, 以符合行长限制. 关于正文哈希如何计算, 见 Section 3.7.

ABNF:

sig-bh-tag = %x62 %x68 [FWS] "=" [FWS] sig-bh-tag-data
sig-bh-tag-data = base64string

c= 规范化

类型: plain-text; OPTIONAL (默认值为 "simple/simple")

此 tag 告知 Verifier 为签名准备消息时所使用的规范化类型. 它由两个名称组成, 中间以 "slash" (%d47) 字符分隔, 分别对应 header 和正文规范化算法. 这些算法在 Section 3.4 中描述. 如果只命名一个算法, 则该算法用于 header, 而正文使用 "simple". 例如, "c=relaxed" 与 "c=relaxed/simple" 按相同方式处理.

ABNF:

sig-c-tag = %x63 [FWS] "=" [FWS] sig-c-tag-alg ["/" sig-c-tag-alg]
sig-c-tag-alg = "simple" / "relaxed" / x-sig-c-tag-alg
x-sig-c-tag-alg = hyphenated-word ; for later extension

d= 签名域标识符 (Signing Domain Identifier, SDID)

类型: plain-text; REQUIRED

SDID 声明对把消息引入邮件流承担责任. 因此, SDID 值用于构造公钥查询. SDID MUST 对应一个有效 DNS 名称, DKIM key record 发布在该名称之下. Signer 创建和使用特定 SDID 所采用的约定和语义超出本规范范围, 对这些约定和语义的任何使用也同样超出本规范范围. 遇到不满足这些要求的签名时, Verifier MUST 认为该签名无效.

国际化域名 MUST 按 [RFC5890] Section 2.3 中的描述编码为 A-label.

ABNF:

sig-d-tag = %x64 [FWS] "=" [FWS] domain-name
domain-name = sub-domain 1*("." sub-domain)
; from [RFC5321] Domain, excluding address-literal

h= 已签名 Header Field

类型: plain-text; REQUIRED

这是一个以冒号分隔的 header field 名称列表, 用于标识提交给签名算法的 header field. 该字段 MUST 按提交给签名算法的顺序包含完整 header field 列表. 该字段 MAY 包含签名时不存在的 header field 名称; 不存在的 header field 不参与签名计算 (即视为空输入, 包括 header field 名称, 分隔冒号, header field 值以及任何 CRLF 终止符). 该字段 MAY 包含同一 header field 名称的多个实例, 表示对应 header field 的多个出现项包含在 header 哈希中. 该字段 MUST NOT 包含正在创建或验证的 DKIM-Signature header field, 但可以包含其他 DKIM-Signature header field. 冒号分隔符两侧 MAY 包含折叠空白 (FWS). Header field 名称 MUST 以大小写不敏感方式与实际 header field 名称比较. 此列表 MUST NOT 为空. 关于选择要签名的 header field, 见 Section 5.4; 关于签署单个字段多个实例时的要求, 见 Section 5.4.2.

ABNF:

sig-h-tag = %x68 [FWS] "=" [FWS] hdr-name *( [FWS] ":" [FWS] hdr-name )

INFORMATIVE EXPLANATION: 通过"签署"实际不存在的 header field, Signer 可以让 Verifier 检测签名后插入这些 header field 的情况. 但是, 由于 Signer 不可能知道未来可能定义哪些 header field, 此机制不能用于防止添加任何可能的未知 header field.

INFORMATIVE NOTE: "签署"在签名时不存在的字段, 不仅防止添加字段和值, 也防止添加无值字段.

i= 代理或用户标识符 (Agent or User Identifier, AUID)

类型: dkim-quoted-printable; OPTIONAL (默认值为空 local-part, 后跟 "@", 再后跟来自 "d=" tag 的域)

SDID 代表并承担责任的 AUID. 语法是标准电子邮件地址, 其中 local-part MAY 省略. 地址的域部分 MUST 与 "d=" tag 的值相同, 或者是其子域.

国际化域名 MUST 按 [RFC5890] Section 2.3 中的描述编码为 A-label.

ABNF:

sig-i-tag = %x69 [FWS] "=" [FWS] [ Local-part ] "@" domain-name

AUID 被规定为具有与电子邮件地址相同的语法, 但不必具有相同语义. 特别是, 域名不必在 DNS 中注册, 因而查询时可能无法解析; local-part MAY 来自与任何 mailbox 无关的命名空间. 该命名空间的结构和语义细节由 Signer 决定. Verifier 或 Assessor 对这些细节的任何了解或使用都超出本规范范围. Signer MAY 选择为其 AUID 使用与其用户电子邮件地址相同的命名空间, 也 MAY 选择其他方式表示其用户. 但是, 如果 Signer 希望向接收方提供把 AUID 用作比 SDID 粒度更细的稳定标识符这一选项, 则对于意图被评估为属于同一责任范围的每条消息, Signer SHOULD 使用相同 AUID.

INFORMATIVE NOTE: "i=" tag 的 local-part 是可选的, 因为在某些情况下 Signer 可能无法建立已验证的个人身份. 在这些情况下, Signer 可能希望声明: 虽然它愿意为该域签名, 但无法或不愿承诺该域内的某个具体用户名. 它可以通过包含身份的域部分但不包含 local-part 来做到这一点.

l= 正文长度计数

类型: plain-text unsigned decimal integer; OPTIONAL (默认值为整个正文)

此 tag 告知 Verifier: 加密哈希中包含的电子邮件正文经规范化后的 octet 数量, 从正文前 CRLF 之后的位置 0 开始计数. 此值 MUST NOT 大于规范化消息正文中的实际 octet 数. 更多讨论见 Section 8.2.

INFORMATIVE NOTE: "l=" tag 的值限制为 76 个十进制数字. 此限制并非意在预测未来消息大小, 也不要求实现使用足够大的整数表示来表示最大可能值, 而是提醒实现者在验证期间检查此 tag 及所有其他 tag 的长度, 并在解码该值时测试整数溢出.

ABNF:

sig-l-tag = %x6c [FWS] "=" [FWS] 1*76DIGIT

q= 查询方法

类型: plain-text; OPTIONAL (默认值为 "dns/txt")

这是一个以冒号分隔的查询方法列表, 用于取得公钥. 每个查询方法采用 "type[/options]" 形式, 其中 options 的语法和语义取决于 type 和指定选项. 如果列出多个查询机制, 查询机制的选择 MUST NOT 改变对签名的解释. 实现 MUST 按给出的顺序使用已识别查询机制. 未识别查询机制 MUST 被忽略.

当前唯一有效值是 "dns/txt", 它定义本文档其他位置描述的 DNS TXT resource record (RR) 查找算法. 为 "dns" 查询类型定义的唯一选项是 "txt", 且 MUST 包含该选项. Verifier 和 Signer MUST 支持 "dns/txt".

ABNF:

sig-q-tag = %x71 [FWS] "=" [FWS] sig-q-tag-method 
*([FWS] ":" [FWS] sig-q-tag-method)
sig-q-tag-method = "dns/txt" / x-sig-q-tag-type ["/" x-sig-q-tag-args]
x-sig-q-tag-type = hyphenated-word ; for future extension
x-sig-q-tag-args = qp-hdr-value

s= Selector

类型: plain-text; REQUIRED

用于细分 "d=" (domain) tag 命名空间的 selector.

国际化 selector 名称 MUST 按 [RFC5890] Section 2.3 中的描述编码为 A-label.

ABNF:

sig-s-tag = %x73 [FWS] "=" [FWS] selector

t= 签名时间戳

类型: plain-text unsigned decimal integer; RECOMMENDED (默认值为未知创建时间)

此签名创建的时间. 格式为 UTC 时区中自 1970 年 1 月 1 日 00:00:00 起经过的秒数. 该值以十进制 ASCII 无符号整数表示. 此值不受限于适配 31-bit 或 32-bit 整数. 实现 SHOULD 准备处理至少达到 10^12 的值 (约到公元 200,000 年; 该值适配 40 bit). 为避免拒绝服务攻击, 实现 MAY 把任何超过 12 位数字的值视为无限大. 不计入闰秒. 实现 MAY 忽略带有未来时间戳的签名.

ABNF:

sig-t-tag = %x74 [FWS] "=" [FWS] 1*12DIGIT

x= 签名过期时间

类型: plain-text unsigned decimal integer; RECOMMENDED (默认值为不过期)

格式与 "t=" tag 相同, 表示为绝对日期, 而不是相对于签名时间戳的时间差. 该值以十进制 ASCII 无符号整数表示, 并具有与 "t=" tag 中值相同的约束. 如果 Verifier 的验证时间晚于过期日期, 签名 MAY 被视为无效. 如果能够可靠获得消息首次到达 Verifier 管理域的时间, 验证时间应使用该时间; 否则应使用当前时间. 如果 "x=" tag 和 "t=" tag 同时存在, "x=" tag 的值 MUST 大于 "t=" tag 的值.

INFORMATIVE NOTE: "x=" tag 并非旨在作为反重放防御.

INFORMATIVE NOTE: 由于时钟漂移, 接收方关于何时认为签名过期的判断可能与发送方预期不完全一致. 接收方 MAY 添加一个 "fudge factor" 以容许这种可能漂移.

ABNF:

sig-x-tag = %x78 [FWS] "=" [FWS] 1*12DIGIT

z= 复制的 Header Field

类型: dkim-quoted-printable; OPTIONAL (默认值为 null)

这是一个以竖线分隔的列表, 包含消息签名时存在的选定 header field, 同时包括字段名和值. 它不要求包含签名时存在的所有 header field. 此字段不必包含与 "h=" tag 中所列相同的 header field. Header field 文本本身必须编码竖线 ("|", %x7C) 字符 (即 "z=" 文本中的竖线是元字符, 复制 header field 中任何实际竖线字符都必须编码). 注意, 所有空白都必须编码, 包括冒号与 header field 值之间的空白. 编码后, 为避免行过长, FWS MAY 添加在任意位置; 此类空白 NOT 是 header field 值的一部分, 并且 MUST 在解码前移除.

"h=" tag 引用的 header field 指消息 [RFC5322] header 中的字段, 而不是 "z=" tag 中任何复制字段. 复制的 header field 值用于诊断.

ABNF:

sig-z-tag = %x7A [FWS] "=" [FWS] sig-z-tag-copy *( "|" [FWS] sig-z-tag-copy )
sig-z-tag-copy = hdr-name [FWS] ":" qp-hdr-value

DKIM-Signature Header Field 示例

以下是跨多条续行展开的签名 header field 的 INFORMATIVE EXAMPLE:

DKIM-Signature: v=1; a=rsa-sha256; d=example.net; s=brisbane;
c=simple; q=dns/txt; [email protected];
t=1117574938; x=1118006938;
h=from:to:subject:date;
z=From:[email protected]|To:[email protected]|
Subject:demo=20run|Date:July=205,=202005=203:44:08=20PM=20-0700;
bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;
b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ
VoG4ZHRNiYzR