跳到主要内容

4.3. Multiple Signatures (多个签名)

4.3. Multiple Signatures (多个签名)

单条消息中可包含多个不同签名. 每个不同签名必须具有唯一标签. 这些多个签名可由同一签名者全部添加, 也可来自若干不同签名者. 例如, 签名者可包含多个签名, 以不同密钥或算法对相同消息组成部分签名, 以支持具有不同能力的验证者, 或反向代理在将请求转发至服务主机时可能在字段中包含关于客户端的信息, 包括对客户端原始签名值的签名.

下列非规范性示例以来自客户端的已签名请求开始. 反向代理接收该请求并校验客户端签名:

NOTE: '' line wrapping per RFC 8792

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-Length: 18 Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T
aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: Signature-Input: sig1=("@method" "@authority" "@path"
"content-digest" "content-type" "content-length")
;created=1618884475;keyid="test-key-ecc-p256" Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp
+kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==:

{"hello": "world"}

随后代理在转发至源站之前变更消息, 改变目标主机并添加 [RFC7239] 定义的 Forwarded 头字段:

NOTE: '' line wrapping per RFC 8792

POST /foo?param=Value&Pet=dog HTTP/1.1 Host: origin.host.internal.example Date: Tue, 20 Apr 2021 02:07:56 GMT Content-Type: application/json Content-Length: 18 Forwarded: for=192.0.2.123;host=example.com;proto=https Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T
aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: Signature-Input: sig1=("@method" "@authority" "@path"
"content-digest" "content-type" "content-length")
;created=1618884475;keyid="test-key-ecc-p256" Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp
+kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==:

{"hello": "world"}

代理能够校验传入的客户端签名, 并通过对转发前的新消息添加自身签名, 向源站就其转发的请求性质作出陈述. 代理还纳入原始消息中与源站处理相关的全部元素. 许多情况下, 代理希望覆盖客户端签名所覆盖的相同组成部分, 下列示例即属此情况. 注意本示例中代理对新的 authority 值签名, 该值已被其更改. 代理还将其自身签名值纳入 Forwarded 头字段. 代理标识其自身密钥与算法, 本示例中还包含过期时间, 以向下游系统表明代理不会在该短时间窗口之后为此签名消息背书. 这产生如下签名基:

NOTE: '' line wrapping per RFC 8792

"@method": POST "@authority": origin.host.internal.example "@path": /foo "content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX
+TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: "content-type": application/json "content-length": 18 "forwarded": for=192.0.2.123;host=example.com;proto=https "@signature-params": ("@method" "@authority" "@path"
"content-digest" "content-type" "content-length" "forwarded")
;created=1618884480;keyid="test-key-rsa";alg="rsa-v1_5-sha256"
;expires=1618884540

以及如下签名输出值:

NOTE: '' line wrapping per RFC 8792

S6ZzPXSdAMOPjN/6KXfXWNO/f7V6cHm7BXYUh3YD/fRad4BCaRZxP+JH+8XY1I6+8Cy
+CM5g92iHgxtRPz+MjniOaYmdkDcnL9cCpXJleXsOckpURl49GwiyUpZ10KHgOEe11s
x3G2gxI8S0jnxQB+Pu68U9vVcasqOWAEObtNKKZd8tSFu7LB5YAv0RAGhB8tmpv7sFn
Im9y+7X5kXQfi8NMaZaA8i2ZHwpBdg7a6CMfwnnrtflzvZdXAsD3LH2TwevU+/PBPv0
B6NMNk93wUs/vfJvye+YuI87HU38lZHowtznbLVdp770I6VHR6WfgS9ddzirrswsE1w
5o0LV/g==

这些值由代理加入 HTTP 请求消息. 原始签名以标签 sig1 纳入, 反向代理的签名以标签 proxy_sig 纳入. 代理使用密钥 test-key-rsa 与 rsa-v1_5-sha256 签名算法创建其签名, 而客户端原始签名使用密钥 test-key-rsa-pss 与 RSA-PSS 签名算法:

NOTE: '' line wrapping per RFC 8792

POST /foo?param=Value&Pet=dog HTTP/1.1 Host: origin.host.internal.example Date: Tue, 20 Apr 2021 02:07:56 GMT Content-Type: application/json Content-Length: 18 Forwarded: for=192.0.2.123;host=example.com;proto=https Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T
aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: Signature-Input: sig1=("@method" "@authority" "@path"
"content-digest" "content-type" "content-length")
;created=1618884475;keyid="test-key-ecc-p256",
proxy_sig=("@method" "@authority" "@path" "content-digest"
"content-type" "content-length" "forwarded")
;created=1618884480;keyid="test-key-rsa";alg="rsa-v1_5-sha256"
;expires=1618884540 Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp
+kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==:,
proxy_sig=:S6ZzPXSdAMOPjN/6KXfXWNO/f7V6cHm7BXYUh3YD/fRad4BCaRZxP+
JH+8XY1I6+8Cy+CM5g92iHgxtRPz+MjniOaYmdkDcnL9cCpXJleXsOckpURl49G
wiyUpZ10KHgOEe11sx3G2gxI8S0jnxQB+Pu68U9vVcasqOWAEObtNKKZd8tSFu7
LB5YAv0RAGhB8tmpv7sFnIm9y+7X5kXQfi8NMaZaA8i2ZHwpBdg7a6CMfwnnrtf
lzvZdXAsD3LH2TwevU+/PBPv0B6NMNk93wUs/vfJvye+YuI87HU38lZHowtznbL
Vdp770I6VHR6WfgS9ddzirrswsE1w5o0LV/g==:

{"hello": "world"}

虽然代理还可将客户端的 Signature 字段值与来自原始消息的 Signature-Input 字段纳入新签名的被覆盖组成部分, 由于第 7.3.7 节讨论的已知对签名值再签名的弱点, 不建议这样做. 代理能够校验客户端签名, 代理对消息的变更将使源站看到消息时既有签名失效. 本示例中, 源站有可能在其签名上下文中具有附加信息以解释 authority 的变更, 尽管该做法需要附加配置与额外谨慎, 见第 7.4.4 节. 在其他应用中, 源站自身可能无法验证原始签名, 但仍希望验证代理已对客户端签名进行适当校验. 需要安全地发出签名已成功处理或接收信号的应用必须仔细规定发送此类信号的替代机制.