Node JS crypto,无法在带重音的字符上创建hmac

时间:2012-08-30 11:06:19

标签: node.js utf-8 hmac non-ascii-characters node-crypto

当我尝试加密的文本具有重音字符(例如ä,ï,ë)时,我遇到了在NodeJS中生成正确签名(使用crypto.js)的问题

generateSignature = function (str, secKey) { 
 var hmac = crypto.createHmac('sha1', secKey);
 var sig = hmac.update(str).digest('hex');
 return sig;
};

如果'str'不包含重音字符(如ä,ï,ë等字符),则此函数将返回正确的HMAC签名。如果文本中存在重音字符,则不会返回正确的HMAC。重音字符在UTF8编码中有效,所以我不知道为什么加密有问题。可能是我需要以某种方式告诉加密我正在签署utf8编码文本,但我不知道如何做到这一点。

此帖中描述了完全相同的问题:NodeJS hmac digest issue with accents 然而,帖子本身以及答案对我来说没有意义(因为他们正在传递他们想要加密的数据,秘密密钥应该去哪里)。

以下是str和secKey的硬编码值的代码版本:

  var crypto = require('crypto');

  str="äïë";  
  secKey="secret"; 
  var hmac = crypto.createHmac('sha1', secKey);
  var sig = hmac.update(new Buffer(str, 'utf8')).digest('hex');
  console.log("Sig:      " + sig);
  console.log("Expected: 094b2ba039775bbf970a58e4a0a61b248953d30b"); 
  // "Expected" was generated using http://hash.online-convert.com/sha1-generator

输出:

Sig:39c9f1a6094c76534157739681456e7878557f58

预期:094b2ba039775bbf970a58e4a0a61b248953d30b

谢谢

1 个答案:

答案 0 :(得分:19)

crypto模块使用的默认编码通常为'binary'。因此,您必须通过'utf-8'指定Buffer才能将其用作编码:

var sig = hmac.update(new Buffer(str, 'utf-8')).digest('hex');

这就是the answer for the other question所展示的,只是为了关键:

var hmac = crypto.createHmac('sha1', new Buffer(secKey, 'utf-8'));

您还可以使用Buffer查看差异:

new Buffer('äïë', 'binary')
// <Buffer e4 ef eb>

new Buffer('äïë', 'utf-8')
// <Buffer c3 a4 c3 af c3 ab>

[修改

运行您提供的示例代码,我得到:

Sig:      094b2ba039775bbf970a58e4a0a61b248953d30b
Expected: 094b2ba039775bbf970a58e4a0a61b248953d30b

然后,稍微修改一下,我得到true

var crypto = require('crypto');

function sig(str, key) {
  return crypto.createHmac('sha1', key)
    .update(new Buffer(str, 'utf-8'))
    .digest('hex');
}

console.log(sig('äïë', 'secret') === '094b2ba039775bbf970a58e4a0a61b248953d30b');