Github推送事件签名不匹配。

36

我正在编写一个 GitHub Webhook,并在 KOA.js 中实现了安全验证:

function sign(tok, blob) {
  var hmac;

  hmac = crypto
    .createHmac('sha1', tok)
    .update(blob)
    .digest('hex');

  return 'sha1=' + hmac;
}

...

key = this.request.headers['x-hub-signature'];
blob = JSON.stringify(this.request.body);

if (!key || !blob) {
  this.status = 400;
  this.body = 'Bad Request';
}

lock = sign(settings.api_secret, blob);

if (lock !== key) {
  console.log(symbols.warning, 'Unauthorized');
  this.status = 403;
  this.body = 'Unauthorized';
  return;
}

...

对于 pull_requests 和 create 事件,这样做是可以的,甚至推送新分支也可以,但是对于推送提交事件,x-hub-signature和从有效载荷计算出的哈希值不匹配,所以它总是得到 403 未授权错误。

更新

我注意到对于这种类型的推送有效载荷,提交和 head_commit 被添加到了有效载荷中。我尝试从正文中删除提交和 head_commit,但这没有起作用。

更新

有关更多信息,请查看这些示例有效载荷。我还包括了测试仓库和令牌信息的 URL:https://gist.github.com/marcoslhc/ec581f1a5ccdd80f8b33


“Fails miserably” 是什么意思?你遇到了哪些错误? - Chris
“x-hub-signature” 不等于计算出的哈希值。 - marcoslhc
2
完全是瞎猜,但你确定 this.request.body 不已经是一个字符串了吗?如果是的话,它将被双重编码(例如,三个字符的字符串 foo 将被 JSON 编码为五个字符的字符串 "foo")。看看 typeof this.request.body 会产生什么结果。 - apsillers
你能否提供一个有问题的事件负载(来自事件API),x-hub-signature的值,你计算出的HMAC和密钥?显然,这应该来自一个测试存储库。 - javabrett
1
您可以在此处查看示例数据以及令牌详细信息:https://gist.github.com/marcoslhc/ec581f1a5ccdd80f8b33 - marcoslhc
1个回答

11

Crypto hash.update()的默认编码为二进制,如在Node JS加密中所述。这会导致您的推送事件有效负载出现问题,其中包含“Hernández”中四个 U+00E1 字符LATIN SMALL LETTER A WITH ACUTE,而GitHub服务正在对该有效负载进行 utf-8 编码的哈希处理。请注意,您的Gist以ISO-8859-1的不正确编码方式显示这些字符,因此还要确保正确处理传入请求的字符编码(但这应该是默认的)。

要解决此问题,您需要使用Buffer之一:

hmac = crypto.createHmac('sha1', tok).update(new Buffer(blob, 'utf-8')).digest('hex');

...或直接将编码传递给update

hmac = crypto.createHmac('sha1', tok).update(blob, 'utf-8').digest('hex');

然后将计算出7f9e6014b7bddf5533494eff6a2c71c4ec7c042d的正确哈希值。


1
好的。我要试试 :) 现在完全明白了! - marcoslhc
标志应该是 utf8 而不是 utf-8 - Joseph Lust
@JosephLust 谢谢,也许两者都可以正常工作 - console.log(Buffer.isEncoding('utf-8')); true console.log(Buffer.isEncoding('utf8')); true - javabrett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接