I have code that is working in my PHP app. In the PHP I sign the url with the following code:
private static function __getHash($string)
{
return hash_hmac('sha1', $string, self::$__secretKey, true);
}
I am attempting to sign the URL in the same way in a Node.js application. This is what I'm trying:
S3.prototype.getHash = function(string){
var key = this.secret_key;
var hmac = crypto.createHash('sha1', key);
hmac.update(string);
return hmac.digest('binary');
};
However, I am getting the following error:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
Do these pieces of code do the same thing? Am I missing something?
This answer from Chris is good if you are porting hash_hmac
with the last parameter being true
. In this case, binary is produced, as is the case with Chris's javascript.
To add to that, this example:
$sign = hash_hmac('sha512', $post_data, $secret);
Would be ported with a function like so in nodejs:
const crypto = require("crypto");
function signHmacSha512(key, str) {
let hmac = crypto.createHmac("sha512", key);
let signed = hmac.update(Buffer.from(str, 'utf-8')).digest("hex");
return signed
}
The difference here being that when you leave off the last argument to hash_hmac (or set it to something not true
), it behaves as defined in the PHP docs:
When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
In order to do this with node.js we use digest('hex')
as you can see in the snippet.