【问题标题】:How to compare HMAC SHA256 signatures from request body in NodeJS如何比较 NodeJS 中请求正文中的 HMAC SHA256 签名
【发布时间】:2021-07-19 19:13:49
【问题描述】:

我正在尝试使用 Dropbox 的 API,我让它通过 webhook 成功向我发送警报,但现在我想在每次他们向我发送警报时验证签名。

从 Dropbox 的文档中,他们写道:

“每个通知请求都将包含一个名为 X-Dropbox-Signature 的标头,其中包含请求正文的 HMAC-SHA256 签名,使用您的应用程序密钥作为签名密钥。这让您的应用程序可以验证通知是否真的来自 Dropbox。”

所以我成功捕获了该签名,并使用 NodeJS 内置的加密模块尝试使用 HMAC SHA256 创建我自己的签名,然后将我的签名与 Dropbox 发送给我的签名进行比较。

这是我这样做的代码:

  var sign = req.get("X-Dropbox-Signature");
  console.log(sign);
  var hmac = crypto.createHmac(algorithm, secret);
  hmac.update(JSON.stringify(req.body));
  hash = hmac.digest('hex');
  console.log(hash);

算法只是'sha256' secret 是我从 Dropbox 应用程序页面获得的密钥。 我必须使用 JSON.stringify(req.body) 因为 req.body 是一个对象而 hmac.update 需要一个字符串。我想知道这是否是我的错误的来源?

我在控制台记录签名,它是来自 Dropbox 的签名,然后我在控制台记录我使用 hmac 创建的签名,但它是不同的签名。

对我可能做错的任何建议?

【问题讨论】:

  • 乍一看,JSON.stringify(req.body) 看起来很可疑。您需要获取原始请求正文的 HMAC,因此如果 req.bodyObject,那可能不是正确的值。我建议您查看 Web 框架的文档,了解如何仅检索原始/原始请求正文。

标签: node.js dropbox dropbox-api sha256 hmac


【解决方案1】:

格雷格是对的。您需要使用原始正文请求来检查消息的成分。以下代码使用 body-parser 库来提取原始正文。

var bodyParser = require("body-parser");

app.use(bodyParser.json({verify:function(req,res,buf){req.rawBody=buf}}))

那么对于post方法:

app.post('/webhooks', function(req, res) {

    const retrievedSignature = req.get("X-header-Integrity")
    //send this body string for validation with secret
    const bodyString = Buffer.from(req.rawBody, 'utf8')

    let check = integrityCheck(retrievedSignature, bodyString, "secret")

});

【讨论】:

  • 很好,但问题没有提到使用 Express 服务器...您可以添加一个示例而不使用无法访问原始正文的 Express 服务器吗?
  • 我添加了一个使用 Node 原生 HTTP 服务器的示例,但我不确定服务器如何无法访问原始请求正文。
【解决方案2】:

以下 sn-p 是使用 Node 的原生 HTTP 服务器计算请求正文的 HMAC 的基本示例。在 Express 中间件中可以非常轻松(并且更简洁地)应用相同的概念。

const http = require('http');
const crypto = require('crypto');

const APP_SECRET = 'prozr59vkis4454';
const REQUEST_BODY = '{"list_folder": {"accounts": ["dbid:AABL4QRrY7tB9viLgPUqmjkzE6Fe5ujlnlE"]}, "delta": {"users": [22575230]}}';
const SIGNATURE = 'aa2508fb90b757aa382edb0815c7f7df0ce1943c53f28fae96e1dc9eb7f677b1';

const server = http
  .createServer((req, res) => {
    const hmac = crypto.createHmac('sha256', APP_SECRET).setEncoding('hex');
    req
      .pipe(hmac)
      .on('finish', () => {
        console.log('signature from header:', req.headers['x-dropbox-signature']);
        console.log('calculated signature: ', hmac.read());
        res.writeHead(204);
        res.end();
      });
  })
  .listen(1313, () => {
    const request = http.request({
      host: 'localhost',
      port: 1313,
      method: 'POST',
    }, () => {
      server.close();
    });

    request.setHeader('x-dropbox-signature', SIGNATURE);

    request.write(REQUEST_BODY);
    request.end();
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-17
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多