unicode字符时,NodeJS中的encryption失败

我正在尝试使用NodeJS Crypto库validation数据完整性。 它需要计算一个JSONstring的Hmac。

经过一些testing后,我已经能够find问题:只要它包含一个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一样的正确结果。

我在这里做错了什么?

谢谢!

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

如果您使用的是较旧的PHP版本,则这些转义序列将被逐字传递(所以\u0026是一个6字符的子string),而Node会将其解释为单个字符( & )。

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

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

当你这样做的时候,Node和PHP的结果是一样的( 0CE0++Kn9mi5xd7nAz/mWOrr7939RWwzfxhBzxAWtAk=准确)。

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

你必须面对一个字符集问题。 您在node.js中将缓冲区显式转换为UTF-8。 这样你就有了一个UTF-8编码string的二进制表示forms的散列。

我打赌PHP内部处理另一个字符集(也许Unicode),这将提供一个不同的string的二进制表示forms。

为了做好事情,你必须保证在散列之前将两者转换成相同的二进制表示。

更新:我只注意到你直接散列string,并将散列表示转换为UTF8。 您必须反转此行为:将string转换为UTF-8之前的散列。 你必须在PHP中继续。 两个平台都必须同意哈希之前的编码。