【问题标题】:How can I verify an HTTP HMAC Signature in Bash?如何在 Bash 中验证 HTTP HMAC 签名?
【发布时间】:2021-06-10 03:45:13
【问题描述】:

我需要验证我使用的程序的 HTTP HMAC 签名(Drone CI,尝试创建扩展),但我没有尝试让结果匹配。

具体来说,HTTP 请求如下所示:

POST / HTTP/1.1
Host: 127.0.0.1
User-Agent: Go-http-client/1.1
Content-Length: 50
Accept: application/vnd.drone.validate.v1+json
Accept-Encoding: identity
Content-Type: application/json
Date: Wed, 09 Jun 2021 01:25:07 GMT
Digest: SHA-256=digest
Signature: keyId="hmac-key",algorithm="hmac-sha256",signature="signature",headers="accept accept-encoding content-type date digest"

{"data":"data"}

我尝试过使用sha256sumhmac256openssl,交换Digestsignature 的值,但它们都没有匹配。


更新:

我已经尝试了以下代码,但它似乎仍然无法正常工作:

MESSAGE='{"data":"data"}'
SECRET="secret" # This isn't any value in the request, is it?

echo -n "${MESSAGE}" | openssl dgst -sha256 -hmac "${SECRET}" | base64 -w 0

更新 2:

HMAC examples on Wikipedia 对我来说工作得很好。我可能会从 HTTP 请求中搞砸什么?

如果值得的话,请求签名显然是基于draft-cavage-http-signatures-10


更新 3:

我尝试使用以下格式创建签名,但仍然没有骰子:

{"data":"data"}
accept: application/vnd.drone.validate.v1+json
accept-encoding: identity
content-type: application/json
date: Wed, 09 Jun 2021 01:25:07 GMT
digest: SHA-256=digest

假设上面的文本存储在变量${hmac_data}下,下面是用来尝试(但失败)达到signature的值:

echo -n "${hmac_data}" | openssl dgst -sha256 -hmac "${key}" | awk '{print $2}' | base64 -w 0

更新 4:

经过一大堆杂乱无章的事情,Kiskae's answer 让我找到了解决方案。

除了他说的,我发现 Drone base64 编码的是 binary 版本的字符串,而不是 ASCII 的。

因此,上述命令的新版本(与 Drone CI 一起使用时)如下:

${MESSAGE} 等于:

accept: application/vnd.drone.validate.v1+json
accept-encoding: identity
content-type: application/json
date: Wed, 09 Jun 2021 01:25:07 GMT
digest: SHA-256=digest

还有命令:

echo -n "${MESSAGE}" | openssl dgst -sha256 -hmac "${SECRET}" -binary | base64 -w 0

【问题讨论】:

  • 暂时忽略 bash,你读过这个吗? stackoverflow.com/questions/18687926/…
  • 我检查了它,我想我了解 HMAC 签名的工作原理,但我仍然没有得到任何匹配的结果。
  • @Thomas 我已经添加了一个我在上面尝试过的小脚本,仍然没有任何运气。

标签: bash http hmac drone.io


【解决方案1】:

他们似乎正在使用http signatures draft 的实现。

链接的文档解释了需要计算签名的方式以及如何验证它。但这可能是您的示例不起作用的原因:

2.1.3。标题

可选。 headers参数用于指定列表 为消息生成签名时包含的 HTTP 标头。

基本上签名不只包含消息,可能是为了防止重放攻击。由于您只是散列消息,因此它按预期工作。

【讨论】:

  • 奇怪,刚刚在您发布时提到了这一点。如果它必须按任何特定顺序,你会吗? (即字符串 - 标题,或标题 - 字符串)
  • 是的,因为字节顺序改变了哈希结果,任何顺序的改变都会完全改变结果。文档的2.3 部分描述了应该如何构造需要散列的字符串。
  • 你知道我是否还在做错事吗?我已经玩了大约两个小时,但一切都还没有匹配。 (我目前正在做的事情发布在“更新 3”下。)
  • 似乎消息正文不是签名的一部分,只有列出的标头(或默认标头)被散列。消息正文的安全性可以通过包含Digest 标头来保证,在签名中包含摘要标头并单独验证摘要。
  • 我想我发现了这个问题 - Drone 正在从 binary 版本的字符串中编码 base64 中的签名。我是来自 ASCII 字符串的 base64 编码,我假设这是导致问题的原因。
猜你喜欢
  • 1970-01-01
  • 2013-09-12
  • 2019-04-14
  • 1970-01-01
  • 2016-03-20
  • 2014-02-28
  • 2018-12-23
  • 2015-01-04
  • 2021-05-04
相关资源
最近更新 更多