12

暗号化しようとしているテキストにアクセント付き文字(ä、ï、ëなど)が含まれている場合、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ダイジェストの問題 ただし、投稿自体と回答は私には意味がありません(暗号化するデータを秘密鍵が必要な場所に渡すため)行く)。

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

ありがとう

4

1 に答える 1

20

cryptoモジュールで使用されるデフォルトのエンコーディングは通常'binary'. したがって、エンコーディングとして使用するには'utf-8'、 a を介して指定する必要があります。Buffer

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

それが、他の質問の答えが示していたものです。キーだけです。

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');
于 2012-08-30T11:51:08.797 に答える