Github 推送事件签名不匹配

Github push event signature don't match

我正在编写 Webhook for GitHub,并在 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;
}

...

for pull_requests 并创建事件这工作正常,即使推送新分支也有效,但对于推送提交事件,x-hub-signature 和从有效负载计算的哈希值不匹配,所以它总是获得 403 未经授权。

更新

我注意到对于这种推送有效载荷,提交和 head_commit 被添加到有效载荷中。我试过从正文中删除提交和 head_commit 但它没有用。

更新

有关更多信息,请查看这些示例负载。我还包括 url 用于测试回购和令牌信息:https://gist.github.com/marcoslhc/ec581f1a5ccdd80f8b33

default encoding of Crypto hash.update() is binary as detailed in the answer to Node JS crypto, cannot create hmac on chars with accents。这会导致您的推送事件有效载荷出现问题,其中包含字符 U+00E1 LATIN SMALL LETTER A WITH ACUTE in Hernández 四次,以及 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 的正确哈希值。