当前位置: 首页 > 知识库问答 >
问题:

GitHub Webhook机密从不验证

洪楚
2023-03-14

我使用GitHub webhook将事件传递到我的一个应用程序(GitHub的Hubot的一个实例),它由sha1机密保护。

我正在使用以下代码来验证传入webhooks上的哈希值

crypto    = require('crypto')
signature = "sha1=" + crypto.createHmac('sha1', process.env.HUBOT_GITHUB_SECRET).update( new Buffer request.body ).digest('hex')
unless request.headers['x-hub-signature'] is signature
  response.send "Signature not valid"
  return

在网络钩子中传递的X-Hub-Signature标头如下所示

X-Hub-签名:sha1=1cffc5d4c77a3f696ecd9c19dbc2575d22ffebd4

我按照GitHub的文档准确地传递了密钥和数据,但哈希结果总是不同的。

这是GitHub的文档。https://developer.github.com/v3/repos/hooks/#example

这是我最有可能误解的部分

秘密:作为X-Hub-Signature标头随HTTP请求传递的可选字符串。此标头的值被计算为正文的HMAC十六进制摘要,使用秘密作为密钥。

有人能看出我哪里错了吗?

共有3个答案

郗欣嘉
2023-03-14

除了Patrick的回答之外,我还建议将Express与它的body解析器一起使用。下面是完整的示例。这适用于Express 4. x、Node 8. x(截至撰写本文时的最新版本)。

请替换YOUR_WEBHOOK_SECRET_HERE并在授权成功函数中执行某些操作。

// Imports
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');

const app = express();
// The GitHub webhook MUST be configured to be sent as "application/json"
app.use(bodyParser.json());

// Verification function to check if it is actually GitHub who is POSTing here
const verifyGitHub = (req) => {
  if (!req.headers['user-agent'].includes('GitHub-Hookshot')) {
    return false;
  }
  // Compare their hmac signature to our hmac signature
  // (hmac = hash-based message authentication code)
  const theirSignature = req.headers['x-hub-signature'];
  const payload = JSON.stringify(req.body);
  const secret = 'YOUR_WEBHOOK_SECRET_HERE'; // TODO: Replace me
  const ourSignature = `sha1=${crypto.createHmac('sha1', secret).update(payload).digest('hex')}`;
  return crypto.timingSafeEqual(Buffer.from(theirSignature), Buffer.from(ourSignature));
};

const notAuthorized = (req, res) => {
  console.log('Someone who is NOT GitHub is calling, redirect them');
  res.redirect(301, '/'); // Redirect to domain root
};

const authorizationSuccessful = () => {
  console.log('GitHub is calling, do something here');
  // TODO: Do something here
};

app.post('*', (req, res) => {
  if (verifyGitHub(req)) {
    // GitHub calling
    authorizationSuccessful();
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Thanks GitHub <3');
  } else {
    // Someone else calling
    notAuthorized(req, res);
  }
});

app.all('*', notAuthorized); // Only webhook requests allowed at this address

app.listen(3000);

console.log('Webhook service running at http://localhost:3000');
骆文彬
2023-03-14

补充Patrick的答案。使用加密很好。timingSafeEqual用于比较HMAC摘要或秘密值。方法如下:

const blob = JSON.stringify(req.body);  
const hmac = crypto.createHmac('sha1', process.env.GITHUB_WEBHOOK_SECRET);
const ourSignature = `sha1=${hmac.update(blob).digest('hex')}`;

const theirSignature = req.get('X-Hub-Signature');

const bufferA = Buffer.from(ourSignature, 'utf8');
const bufferB = Buffer.from(theirSignature, 'utf8');

const safe = crypto.timingSafeEqual(bufferA, bufferB);

if (safe) {
  console.log('Valid signature');
} else {
  console.log('Invalid signature');
}

要了解更多关于像timing相等这样的安全比较和简单的===之间的区别,请在此处查看此线程。

加密。在节点中添加了timingSafeEqual。js v6.6.0

纪鸿禧
2023-03-14

似乎不适用于Buffer,而是JSON. stringify();这是我的工作代码:

var
  hmac,
  calculatedSignature,
  payload = req.body;

hmac = crypto.createHmac('sha1', config.github.secret);
hmac.update(JSON.stringify(payload));
calculatedSignature = 'sha1=' + hmac.digest('hex');

if (req.headers['x-hub-signature'] === calculatedSignature) {
  console.log('all good');
} else {
  console.log('not good');
}
 类似资料:
  • 我正在尝试在WooCommerce Webhook API和我的节点之间创建一个集成。js后端。然而,我真的不知道应该如何使用这个秘密来验证请求。 机密:一个可选的密钥,用于生成请求正文的HMAC-SHA256哈希,以便接收方可以验证webhook的真实性。 返回以下值: :pU9kXddJPY9MG9i2ZFLNTu3TXZA 85pnwfPqmr0dg0= 签名:PjKImjr9Hk9MmId

  • 问题内容: 我的 詹金斯(Jenkins) 有问题,设置为“ git”,显示以下错误: 我已经用 ssh 测试过: 这是错误的: 我还使用“ SSH密钥”完成了这些步骤。 在詹金斯下登录 将您的github密钥复制到Jenkins .ssh文件夹 重命名键 但仍然无法在 jenkins中使用* git 仓库。 * 感谢帮助!。 问题答案: 更改为用户并手动运行命令: 首次通过SSH连接到新主机时,

  • 问题内容: 我正在使用pysftp编写程序,它想针对验证SSH主机密钥。 终端程序使用PuTTY将其保存到Registry中。 如何调和pysftp和PuTTY之间的区别? 我的代码是: E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py:61: UserWarning: Failed to load HostK

  • 我对jenkins有一个问题,设置“Git”,显示以下错误: 我已经用ssh进行了测试: 这是错误: 谢谢你的帮助!。

  • 使用PuTTY,终端程序将其保存到注册表。 如何协调pysftp和Putty之间的差异? 我的代码是:

  • 此代码引发异常。如何验证SSH指纹而不将其存储在文件中?我相信下面的代码是为公钥设计的。但带有SFTP服务器的客户端验证了指纹,但没有为我获取公钥。 代码基于使用PysFTP验证主机密钥。