Javascript 如何将Buffer.from()与crypto.timingSafeEqual()一起使用?

Javascript 如何将Buffer.from()与crypto.timingSafeEqual()一起使用?,javascript,node.js,ecmascript-6,Javascript,Node.js,Ecmascript 6,因为某种原因,我得到了 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 从两个参数到加密计时安全相等(a,b) 我也试过了 const a = Buffer.from(signature, 'utf8').to

因为某种原因,我得到了

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
从两个参数到
加密计时安全相等(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}`));
我看到两个问题:

  • 第一个也是主要的一个是
    isSigOk
    假设作为
    “X-Hub-Signature-256”
    标题的值:

    const signature = request.headers["X-Hub-Signature-256"];
    const a = Buffer.from(signature);
    
    如果
    signature
    undefined
    ,则该
    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);
    };
    
  • 资本化很重要。根据从Node.js的
    IncomingMessage
    继承的(Express的
    Requset
    对象),
    headers
    中的头名称是小写的。因此
    request.headers[“X-Hub-Signature-256”]
    应该是
    request.headers[“X-Hub-Signature-256”]
    。(在一条注释中,您说您得到了一个值,但注释使用了所有小写字母,而代码使用混合大小写。)因此:


  • 我不认为错误来自于
    定时安全相等
    ,我认为它来自
    缓冲区。(如果执行
    Buffer.from(undefined)
    ,您会得到完全相同的错误,这告诉我
    request.headers[“X-Hub-Signature-256”]
    undefined
    @T.J.Crowder,当我
    console.log
    这个
    const Signature=request.headers[“X-Hub-Signature-256”]我得到了
    sha256=01DF1FFC00107AB2E8782BA7983BB7245DF79B6B414D4E89F8357144D6163CB
    ,所以我得到了数据?
    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 crypto.timingSafeEqual(a, b);
    };