1

我正在尝试使用 NodeJS Crypto 库验证数据完整性。它需要计算 JSON 字符串的 Hmac。

经过一些测试,我已经能够找到问题:只要它包含一个 unicode 字符就会发生。例如:

var hasher = crypto.createHmac("sha256", 'secret_key');
hasher.write('{"timezone":"(GMT-05:00) Eastern Time (US \u0026 Canada)"}');
hasher.end();

var calculatedHmac = new Buffer(hasher.read(), 'utf8').toString('base64');
console.log(calculatedHmac);

但是,这会返回错误的 hmac。PHP 中的相同代码与我从第三方服务收到的签名相匹配:

$data = '{"timezone":"(GMT-05:00) Eastern Time (US \u0026 Canada)"}';

$calculated_hmac = base64_encode(hash_hmac('sha256', $data, 'secret_key', true));
var_dump($calculated_hmac); // Result is correct here

如果我删除 NodeJS 有效负载中的“\u0026”,那么我会得到与 PHP 相同的正确结果。

我在这里做错了吗?

谢谢!

4

2 回答 2

2

\uXXXX转义序列符号仅受版本 7 的 PHP 支持(参考

如果您使用的是较旧的 PHP 版本,这些转义序列将按字面意思传递(\u00266 个字符的子字符串也是如此),而 Node 会将其解释为单个字符 ( &)。

如果您希望 Node 停止解释转义序列,则需要转义反斜杠:

hasher.write('{"timezone":"(GMT-05:00) Eastern Time (US \\u0026 Canada)"}');

当你这样做时,Node 和 PHP 的结果将是相同的(0CE0++Kn9mi5xd7nAz/mWOrr7939RWwzfxhBzxAWtAk=准确地说)。

于 2016-01-21T14:31:17.093 回答
0

我不是 PHP 专家,但我有一个很好的猜测:

您必须面临字符集问题。您在 node.js 中将缓冲区显式转换为 UTF-8。这样,您就可以从 UTF-8 编码字符串的二进制表示中获得哈希值。

我敢打赌 PHP 在内部处理另一个字符集(可能是 Unicode),它将为您的字符串提供不同的二进制表示。

为了使事情正确,您必须确保在散列之前将两者都转换为相同的二进制表示。

更新:我刚刚注意到您直接对字符串进行哈希处理并将哈希表示形式转换为 UTF8。您必须反转此行为:在散列之前将您的字符串转换为 UTF-8。你必须在 PHP 中进行相同的操作。两个平台都必须在散列之前同意编码。

于 2016-01-21T13:40:40.590 回答