NodeJS 如何使用Buffer.from()和crypto.timingSafeEqual()?

pbpqsu0x  于 2023-05-22  发布在  Node.js
关注(0)|答案(1)|浏览(87)

出于某种原因

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined

从两个参数到crypto.timingSafeEqual(a, b)
我也试过

const a = Buffer.from(signature, 'utf8').toString('base64');
const b = Buffer.from(expectedSignature, 'utf8').toString('base64');

我得到同样的错误。

问题

谁能解释一下为什么这些参数不是缓冲器?

const express = require("express");
const bodyParser = require("body-parser");
const crypto = require('crypto');
const secret = "x";

const app = express();
const PORT = 8080;

app.use(bodyParser.json());

function isSigOk(request, secret) {
    // calculate the signature
    const expectedSignature = "sha256=" +
        crypto.createHmac("sha256", secret)
            .update(JSON.stringify(request.body))
            .digest("hex");

    // compare the signature against the one in the request
    const signature = request.headers["X-Hub-Signature-256"];
    const a = Buffer.from(signature);
    const b = Buffer.from(expectedSignature);
    return crypto.timingSafeEqual(a, b);
};

app.post("/", (req, res) => {
  if (isSigOk(req, secret)) {
    // Do stuff here
  } else {
    console.log('Error: Signatures does not match. Return res.status(401)');
  };
  res.status(200).end();
});

// Start express on the defined port
app.listen(PORT, () => console.log(`Github wekhook listening on port ${PORT}`));
r7xajy2e

r7xajy2e1#

我看到两个问题:
1.第一个也是最主要的一个是isSigOk假设"X-Hub-Signature-256"头部有一个值:

const signature = request.headers["X-Hub-Signature-256"];
const a = Buffer.from(signature);

如果signatureundefined,则Buffer.from调用将抛出您引用的错误,因为头部不存在。在这种情况下,您可能希望返回false(并且可能通过重新排序来跳过计算预期签名的开销),请参阅***注解和相关行:

function isSigOk(request, secret) {
    // *** get the signature on this message, if any
    const signature = request.headers["X-Hub-Signature-256"];
    if (!signature) {
        // *** none
        return false;
    }
    // calculate the signature
    const expectedSignature = "sha256=" +
        crypto.createHmac("sha256", secret)
            .update(JSON.stringify(request.body))
            .digest("hex");

    // compare the signature against the one in the request
    const a = Buffer.from(signature);
    const b = Buffer.from(expectedSignature);
    return crypto.timingSafeEqual(a, b);
};

1.资本化很重要。根据Node.js文档(Express的Request对象继承自Node.js的IncomingMessage),headers的名称是小写的。所以request.headers["X-Hub-Signature-256"]应该是request.headers["x-hub-signature-256"]。(在注解中你说你得到了一个值,但是注解使用了小写,而代码使用了混合大小写。)所以:

function isSigOk(request, secret) {
    // *** get the signature on this message, if any
    const signature = request.headers["x-hub-signature-256"]; // *** Lowercase
    if (!signature) {
        // *** none
        return false;
    }
    // calculate the signature
    const expectedSignature = "sha256=" +
        crypto.createHmac("sha256", secret)
            .update(JSON.stringify(request.body))
            .digest("hex");

    // compare the signature against the one in the request
    const a = Buffer.from(signature);
    const b = Buffer.from(expectedSignature);
    return a.length === b.length && crypto.timingSafeEqual(a, b);
};

请注意其中的a.length === b.length &&部分。timingSafeEqual将抛出一个错误,如果缓冲区不是相同的长度,但我们希望在这种情况下返回false。

相关问题