web-dev-qa-db-ja.com

Node.jsで同等のHash_hmac

PHPアプリで動作しているコードがあります。PHPでは、次のコードでURLに署名します。

private static function __getHash($string)
{
    return hash_hmac('sha1', $string, self::$__secretKey, true);    
}

Node.jsアプリケーションで同じ方法でURLに署名しようとしています。これは私が試していることです:

S3.prototype.getHash = function(string){
    var key = this.secret_key; 
    var hmac = crypto.createHash('sha1', key);
    hmac.update(string); 
    return hmac.digest('binary'); 
}; 

ただし、次のエラーが発生します。

計算したリクエストの署名が、指定した署名と一致しません。キーと署名方法を確認してください。

これらのコードは同じことをしますか?私は何かが足りないのですか?

13
Sara Tibbetts

ここでの主な問題は、HMACを作成するcreateHashではなく、ハッシュを作成するcreateHmacを使用していることです。

createHashcreateHmacに変更すると、同じ結果が得られるはずです。

これはあなたが期待すべき出力です:

chris /tmp/hmac $ cat node.js 
var crypto = require('crypto');
var key = 'abcd';
var data = 'wxyz';

function getHash(string){
    var hmac = crypto.createHmac('sha1', key);
    hmac.update(string); 
    return hmac.digest('binary'); 
};

process.stdout.write(getHash(data));

chris /tmp/hmac $ cat php.php 
<?php
$key = "abcd";
$data = "wxyz";
function __getHash($string)
{
    global $key;
    return hash_hmac('sha1', $string, $key, true); 
}

echo utf8_encode(__getHash($data));

chris /tmp/hmac $ node node.js | base64
WsOKw4xgw4jDlFHDl3jDuEPDuCfCmsOFwoDCrsK/w6ka
chris /tmp/hmac $ php php.php | base64
WsOKw4xgw4jDlFHDl3jDuEPDuCfCmsOFwoDCrsK/w6ka
6
Chris

_hash_hmac_を移植し、最後のパラメーターがtrueである場合、Chrisからのこの回答は適切です。この場合、Chrisのjavascriptの場合と同様に、バイナリが生成されます。

これに加えて、この例:

_ $sign = hash_hmac('sha512', $post_data, $secret);
_

Nodejsでそのような関数で移植されます:

_const crypto = require("crypto");

function signHmacSha512(key, str) {
  let hmac = crypto.createHmac("sha512", key);
  let signed = hmac.update(new Buffer(str, 'utf-8')).digest("hex");
  return signed
}
_

ここでの違いは、hash_hmacの最後の引数を省略した場合(またはtrue以外に設定した場合)、PHP docs)で定義されているように動作することです。

TRUEに設定すると、生のバイナリデータが出力されます。 FALSEは小文字のヘキシットを出力します。

Node.jsでこれを行うには、スニペットに示されているようにdigest('hex')を使用します。

8
keyvan