HMAC SHA1签名与x-hub-signature头不匹配,签名验证求助
解决HMAC签名验证失败的问题
我帮你排查下这个HMAC签名验证失败的问题,核心原因大概率是你用了解析后的request.body对象再通过JSON.stringify()转换回字符串,而不是直接使用原始请求体字节来计算HMAC。当你的后端框架(比如Express)用express.json()中间件解析JSON请求时,它会对原始请求体做格式化处理(比如去除多余空格、调整键的顺序等),这会导致你计算的摘要和发送方基于原始请求体生成的签名完全不一致。
修正步骤:
获取原始请求体
不要使用express.json()解析请求,改用express.raw({ type: 'application/json' })或者express.text({ type: 'application/json' })中间件来获取原始的请求体内容。这样能保证你拿到的是和发送方完全一致的字节数据,避免解析过程中的格式篡改。调整HMAC计算逻辑
直接用原始请求体计算HMAC,不需要再做JSON.stringify()操作——发送方的签名就是基于原始请求体生成的,你得保持计算源一致。
修正后的代码示例:
const sig = request.headers['x-hub-signature'] || ''; // 这里的request.body是原始buffer/字符串,来自raw/text中间件 const hmac = crypto.createHmac('sha1', '56e2a9fa00996dd4b026b55a5134df650acb42c83767dd5456eb2f3496ef85a4'); // 直接用原始请求体更新HMAC hmac.update(request.body); const digest = Buffer.from(`sha1=${hmac.digest('hex')}`, 'utf8'); const checksum = Buffer.from(sig, 'utf8'); if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) { return console.log(`Request body digest (${digest}) did not match X-Hub-Signature (${checksum})`); }
额外注意事项:
- 如果用Express框架,要确保在路由之前先挂载原始请求体的中间件:
// 用raw中间件直接获取buffer app.use(express.raw({ type: 'application/json' })); // 或者用text中间件获取字符串,后续也能正常计算HMAC // app.use(express.text({ type: 'application/json' })); - 确认你的密钥和发送方使用的完全一致,没有多余的空格、换行或字符(复制时很容易踩这个坑)。
- 检查
x-hub-signature的格式是否确实是sha1=xxxxxx,有些服务可能会用sha256等其他哈希算法,如果是这种情况要对应修改createHmac的算法参数。
内容的提问来源于stack exchange,提问作者V K




