如何在 JavaScript 中验证 HMAC SHA256?

问题描述

我正在用 Node.js 编写一个集成了 Todoist、Notion 和 discord 的脚本。我使用 Heroku 进行托管,因为我想使用 webhooks(来自 Todoist)。这个想法是,每次我添加或完成一项任务时,Todoist 都会向我的应用发出通知,在验证请求合法后,我更新我的 Notion 数据库并通过 discord 机器人发送消息。

我遇到的问题是当我必须检查 HMAC SHA256 时。我对 JavaScript 还是很陌生,甚至对散列和密钥还很陌生,所以请耐心等待。

Todoist documentation 说:

为了验证每个 webhook 请求确实是由 Todoist 发送的,包含一个 X-Todoist-Hmac-SHA256 标头;它是使用您的 client_secret 作为加密密钥和整个请求负载作为要加密的消息生成的 SHA256 Hmac。生成的 Hmac 将被编码为 base64 字符串。

经过大量研究,我尝试使用我在another question中找到的一个函数作为验证答案,但发生了这种情况:throw new Error('Malformed UTF-8 data');

这是我目前所拥有的:


const express = require('express');
const discord = require('discord.js');
const client = new discord.Client();
var CryptoJS = require('crypto-js');
require('dotenv').config();

const PORT = process.env.PORT || 3000;

app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

process.on('unhandledRejection',error => {
    // Will print "unhandledRejection err is not defined"
    console.log('unhandledRejection',error.message);
});

function sign_string(message,key){
    var secret_key = CryptoJS.enc.Base64.parse(key).toString(CryptoJS.enc.Utf8);
    var hash = CryptoJS.HmacSHA256(message,secret_key);
    return CryptoJS.enc.Base64.stringify(hash);
}

client.on('ready',() => {
    client.users.fetch(process.env.MY_USER_ID).then(user => user.send('hey,The bot is up!'));
});

app.get('',(req,res) => {
    res.send('Hello World');
});

app.post('',res) => {
    if(req.get('User-Agent') === 'Todoist-Webhooks') {
        var delivered_hmac = req.get('X-Todoist-Hmac-SHA256');
        var computed_hmac = sign_string(JSON.stringify(req.body),process.env.TodoIST_CLIENT_SECRET);
        if(delivered_hmac === computed_hmac) {
            if(req.body.event_name === 'item:added' && req.body.event_data.description === '') {
                // add task to notion
                // idea: ask user for data
            } else {
                if(req.body.event_name === 'item:completed' && req.body.event_data.description !== '') {
                    // complete task on notion
                }
            }
            client.users.fetch(process.env.MY_USER_ID).then(user => user.send('You can update your tasklist if you want'));
            res.status(200).send('Event handled');
        } else {
            client.users.fetch(process.env.MY_USER_ID).then(user => user.send('A 403 (Unauthorized) status code has been sent to a request'));
            res.status(403).send('Unauthorized');
            console.log(`delivered_hmac: ${delivered_hmac}\ncomputed_hmac: ${computed_hmac}\n`)
            console.log(req.body);
        }
    } else {
        client.users.fetch(process.env.MY_USER_ID).then(user => user.send('A 400 (Bad request) status code has been sent to a request'));
        res.status(400).send('Bad request');
    }
    //handle notion


})


client.login(process.env.BOT_TOKEN);
app.listen(PORT,() => {
    console.log(`App up at port ${PORT}`);
});

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)