Reputation: 323
So I am working on a PHP script that queries an API which uses HMAC authentication headers. However, I have been banging my head trying to encode the HMAC signature correctly. I have a preexisting nodejs script to work from as a template.
In the nodejs script, the HMAC signature is calculated using the following:
var crypto = require('crypto');
var hmac = [];
hmac.secret = 'ODc0YTM3YzUxODFlMWQ1YTdhMGQwY2NiZmE1N2Y1ODdjYzM5NTgyMDJhZjVkYTE4MmQxYzQ5ODk0M2QzNWQxYw==';
hmac.timestamp = 1457326475000;
hmac.path = '/account/';
hmac.message = hmac.path +'\n' + hmac.timestamp;
var sig = crypto.createHmac('sha512', new Buffer(hmac.secret, 'base64'));
hmac.signature = sig.update(hmac.message).digest('base64');
console.log(hmac);
This correctly calculates the HMAC signature as: bWjIFFtFmWnj0+xHLW2uWVa6M6DpbIV81uyUWwRFCJUg+0Xyt40QWZWQjGvfPUB/JbjGZHUoso0Qv5JHMYEv3A==.
Meanwhile, in PHP, I am using:
<?php
$hmac['secret'] = 'ODc0YTM3YzUxODFlMWQ1YTdhMGQwY2NiZmE1N2Y1ODdjYzM5NTgyMDJhZjVkYTE4MmQxYzQ5ODk0M2QzNWQxYw==';
$hmac['nonce'] = '1457326475000';
$hmac['path'] = '/account/';
$hmac['message'] = $hmac['path']."\n".$hmac['nonce'] ;
$hmac['signature'] = base64_encode(hash_hmac('sha512',$hmac['message'],
$hmac['secret'], true));
print_r($hmac);
The above code, will calculate the HMAC signature as: vqP49m/bk9nA4S3nMqW2r+kc2+yBfwhY/jWGUfz6dlKJUMkC2ktiPnuCcymdSWl4XezZT5VKCATYfus86Hz/Gg==
Working from the principle that "one million monkeys hacking away at a million keyboards" might one day be able to encode a valid HMAC signature, I have even tested a loop that iterates through all the permutations of the above PHP code (with/without base64 encoding the message, secret; with/without binary encoding of the HMAC, etc.)... to no avail.
Any suggestions for this here, one exhausted simian?
Upvotes: 2
Views: 597
Reputation: 106698
The problem is that you're not decoding your $hmac['secret']
first before passing it to hash_hmac()
.
Try:
$hmac['secret'] = base64_decode($hmac['secret']);
$hmac['signature'] = base64_encode(
hash_hmac('sha512', $hmac['message'], $hmac['secret'], true)
);
Upvotes: 2