You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python与JS中HMAC输出不一致问题求助(不可修改Python代码)

问题原因及解决方案

核心差异点

  1. 哈希数据的处理逻辑:
    • Python中hashlib.sha256(...).digest()返回二进制字节(bytes),直接拼接到字符串时,Python会自动将其转为b'\xXX\xXX...'格式的字符串表示,再通过encode('utf-8')转成字节流参与HMAC计算。
    • 你的JS代码直接将CryptoJS.SHA256的结果(WordArray)转为十六进制字符串,和Python的处理逻辑完全不匹配。
  2. JSON序列化一致性:
    • 虽然Python的json.dumps和JS的JSON.stringify默认行为接近,但要确保对象键顺序、空格处理完全一致(两者默认都不排序键,只要数据结构一致即可)。

修正后的JS代码

情况1:严格匹配Python原代码的字符串拼接逻辑

如果Python代码确实是将bytes对象转为字符串表示后拼接,使用以下代码:

var CryptoJS = require("crypto-js");

const date = "2024-01-16 16:11:11";
const nonce = 'ksjdnf5646512';
const data = {key: 'value'}; // 替换为实际业务的value值
const method = 'PATCH';
const api = 'api';
const content_type = 'application/json';

// 1. 生成和Python json.dumps一致的JSON字符串
const dataStr = JSON.stringify(data);

// 2. 计算SHA256并转为Python风格的bytes字符串表示
const sha256Result = CryptoJS.SHA256(dataStr);
const bytes = [];
for (let i = 0; i < sha256Result.sigBytes; i++) {
    const byte = (sha256Result.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
    bytes.push(byte);
}
const hashedDataStr = `b'${bytes.map(b => `\\x${b.toString(16).padStart(2, '0')}`).join('')}'`;

// 3. 构建待哈希的完整字符串
const stringToHash = `${method}\n${date}\n${api}\n${content_type}\n${nonce}\n${hashedDataStr}`;

// 4. 计算HMAC-SHA256并转为十六进制字符串
const hmacString = CryptoJS.HmacSHA256(stringToHash, 'secretkey').toString(CryptoJS.enc.Hex);

console.log(hmacString);

情况2:修正为常规HMAC签名逻辑(更合理)

如果Python代码是笔误,实际应该拼接各部分的字节流(这是接口签名的常规做法),使用以下代码:

var CryptoJS = require("crypto-js");

const date = "2024-01-16 16:11:11";
const nonce = 'ksjdnf5646512';
const data = {key: 'value'}; // 替换为实际业务的value值
const method = 'PATCH';
const api = 'api';
const content_type = 'application/json';

// 1. 生成一致的JSON字符串并计算SHA256二进制哈希
const dataStr = JSON.stringify(data);
const hashedData = CryptoJS.SHA256(dataStr);

// 2. 拼接所有部分的字节流(包含换行符)
const parts = [
    CryptoJS.enc.Utf8.parse(method),
    CryptoJS.enc.Utf8.parse('\n'),
    CryptoJS.enc.Utf8.parse(date),
    CryptoJS.enc.Utf8.parse('\n'),
    CryptoJS.enc.Utf8.parse(api),
    CryptoJS.enc.Utf8.parse('\n'),
    CryptoJS.enc.Utf8.parse(content_type),
    CryptoJS.enc.Utf8.parse('\n'),
    CryptoJS.enc.Utf8.parse(nonce),
    CryptoJS.enc.Utf8.parse('\n'),
    hashedData
];
const stringToHash = parts.reduce((acc, part) => acc.concat(part), CryptoJS.lib.WordArray.create());

// 3. 计算HMAC-SHA256并转为十六进制字符串
const hmacString = CryptoJS.HmacSHA256(stringToHash, CryptoJS.enc.Utf8.parse('secretkey')).toString(CryptoJS.enc.Hex);

console.log(hmacString);

验证方法

运行Python代码时,打印出string_to_hash和hashed_data的值,对比JS代码中生成的对应内容,确保两者完全一致后,再验证最终的HMAC结果是否匹配。

内容的提问来源于stack exchange,提问作者Deepak Babu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:18:11