跳到主要内容

2.5. Creating the Signature Base (创建签名基)

2.5. Creating the Signature Base (创建签名基)

签名基为 ASCII 字符串 [ASCII], 包含签名所覆盖的经规范化的 HTTP 消息组成部分. 签名基创建算法的输入为被覆盖组成部分标识符的有序集合及其关联值, 以及第 2.3 节讨论的任意附加签名参数.

组成部分标识符使用 [STRUCTURED-FIELDS] 第 4 节定义的严格序列化规则序列化. 标识符具有作为 String Item 值序列化的组成部分名称 (使用 sf-string ABNF 规则). 组成部分标识符还可以包含使用 parameters ABNF 规则序列化的已定义参数. 第 2.3 节定义的签名参数行遵循相同模式, 但标识符为固定值且无参数的 String Item, 组成部分值始终为带可选参数的 Inner List.

注意这意味着组成部分名称本身的序列化包在双引号内, 参数随后作为分号分隔列表, 例如 "cache-control", "@authority", "@signature-params", 或 "example-dictionary";key="foo".

输出为构成签名基的有序字节集, 符合下列 ABNF:

signature-base = *( signature-base-line LF ) signature-params-line
signature-base-line = component-identifier ":" SP
( derived-component-value / *field-content )
; no obs-fold nor obs-text
component-identifier = component-name parameters
component-name = sf-string
derived-component-value = *( VCHAR / SP )
signature-params-line = DQUOTE "@signature-params" DQUOTE
":" SP inner-list

创建签名基时, 签名者或验证者使用下列算法连接签名被覆盖组成部分中各标识符 (含参数) 的条目. 按描述产生的所有错误必须立即使算法失败, 不输出签名基.

  1. 令输出为空字符串.

  2. 对被覆盖组成部分集合中每个消息组成部分项 (按顺序):

    2.1. 若该组成部分标识符 (含参数) 已加入签名基, 产生错误.

    2.2. 按 component-identifier ABNF 规则序列化被覆盖组成部分的标识符并追加. 注意此序列化将组成部分名称置于双引号内并在引号外追加任意参数.

    2.3. 追加单个冒号 (:).

    2.4. 追加单个空格 (" ").

    2.5. 确定该标识符的组成部分值.

    • 若标识符包含无法理解的参数, 产生错误.

    • 若标识符包含彼此互斥的参数 (如 bssf), 产生错误.

    • 若标识符包含 req 参数且目标消息为请求, 产生错误.

    • 若标识符包含 req 参数且目标消息为响应, 组成部分值的上下文为目标响应消息的相关请求消息. 否则组成部分值的上下文为目标消息.

    • 若组成部分名称以 @ 字符开头, 按第 2.2 节为派生组成部分定义的具体规则 (含任意已知有效参数的处理) 从消息推导组成部分的值. 若派生组成部分名称未知或无法推导值, 产生错误.

    • 若组成部分名称不以 @ 开头, 按第 2.1 节 (含任意已知有效参数的处理) 规范化 HTTP 字段值. 若消息找不到字段或无法在上下文中取得值, 产生错误.

    2.6. 追加被覆盖组成部分的规范化组成部分值.

    2.7. 追加单个换行 (\n).

  3. 按 signature-params-line 规则追加签名参数组成部分 (第 2.3 节):

    3.1. 按 component-identifier 规则序列化签名参数的标识符, 即精确值 "@signature-params" (含双引号).

    3.2. 追加单个冒号 (:).

    3.3. 追加单个空格 (" ").

    3.4. 追加第 2.3 节定义的签名参数规范化组成部分值, 即带参数的 Inner List Structured Field 值.

  4. 若输出字符串包含任何非 ASCII 字符 [ASCII], 产生错误.

  5. 返回输出字符串.

若被覆盖组成部分引用无法在消息中解析为组成部分值的标识符, 实现必须产生错误且不创建签名基. 此类情况包括但不限于:

  • 签名者或验证者不理解派生组成部分名称.

  • 组成部分名称标识消息中不存在或值格式错误的字段.

  • 组成部分标识符包含未知或不适用于其所附组成部分标识符的参数.

  • 组成部分标识符指示使用 Structured Field 序列化 (通过 sf 参数), 但已知字段不是 Structured Field 或实现不知道 Structured Field 类型.

  • 组成部分标识符为 Dictionary 成员标识符, 引用消息中不存在的字段, 非 Dictionary Structured Field, 或值格式错误.

  • 组成部分标识符为 Dictionary 成员标识符或命名查询参数标识符, 引用组成部分值中不存在的成员或值格式错误. 例如标识符为 "example-dict";key="c", 而 Example-Dict 头字段值为 a=1, b=2, 没有 c 值.

下列非规范性示例中, 被签名的 HTTP 消息为下列请求:

POST /foo?param=Value&Pet=dog HTTP/1.1
Host: example.com
Date: Tue, 20 Apr 2021 02:07:55 GMT
Content-Type: application/json
Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\
aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==:
Content-Length: 18

{"hello": "world"}

被覆盖组成部分按顺序由派生组成部分 @method, @authority, @path 及 HTTP 头字段 Content-Digest, Content-Length, Content-Type 构成. 签名参数由创建时间戳 1618884473 与密钥标识符 test-key-rsa-pss 构成. 注意此处未给出显式 alg 参数, 因为应用已知验证者根据所标识密钥使用 RSA-PSS 算法. 带这些参数的消息签名基为:

"@method": POST
"@authority": example.com
"@path": /foo
"content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX\
+TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==:
"content-length": 18
"content-type": application/json
"@signature-params": ("@method" "@authority" "@path" \
"content-digest" "content-length" "content-type")\
;created=1618884473;keyid="test-key-rsa-pss"

图 1: 非规范性示例签名基

注意上述示例签名基不包含示例末尾的换行, 本规范其他位置展示的示例签名基同理.