0

I have a PHP script which use HMAC and a key to generate a hash. It works well:

$payload = '1605697463367HELLO';
$key = '861bbfc01e089259091927d6ad7f71c8b46b7ee13499574e83c633b74cdc29e3b7e262e41318c8425c520f146986675fdd58a4531a01c99f06da378fdab0414a';
$expected_result = '82ef9a8178dcb4df0b71540fa06d7da826ecb26e1977e230bdc8c9d6f9f1af84';

print_r([
    hash_hmac('sha256', $payload, $key),
    hash_hmac('sha256', $payload, hex2bin($key)),
    $expected_result
]);
/*
Array
(
    [0] => 466d4640b64eecc71e8a2dbd3bafdda0118295e07214e7a7845189699fcf7aa5
    [1] => 82ef9a8178dcb4df0b71540fa06d7da826ecb26e1977e230bdc8c9d6f9f1af84
    [2] => 82ef9a8178dcb4df0b71540fa06d7da826ecb26e1977e230bdc8c9d6f9f1af84
)
GOOD! [1] matches [2]!
*/

Now I need to translate this into NodeJS. I tried without success these solutions:

const crypto = require('crypto');
const { TextEncoder } = require('util');
const { HmacSHA256 } = require('crypto-js');
const hex2bin = str => str.match(/.{1,2}/g).reduce((str, hex) => str += String.fromCharCode(parseInt(hex, 16)), '');

const payload = '1605697463367HELLO';
const key = '861bbfc01e089259091927d6ad7f71c8b46b7ee13499574e83c633b74cdc29e3b7e262e41318c8425c520f146986675fdd58a4531a01c99f06da378fdab0414a';
const expected_result = '82ef9a8178dcb4df0b71540fa06d7da826ecb26e1977e230bdc8c9d6f9f1af84';

console.log([
    crypto.createHmac('SHA256', key).update(payload).digest('hex'),
    crypto.createHmac('SHA256', hex2bin(key)).update(payload).digest('hex'),
    HmacSHA256(payload, key).toString(),
    HmacSHA256(payload, hex2bin(key)).toString(),
    HmacSHA256((new TextEncoder()).encode(payload), key).toString(),
    HmacSHA256((new TextEncoder()).encode(payload), hex2bin(key)).toString(),
    expected_result
]);
/*
[ '466d4640b64eecc71e8a2dbd3bafdda0118295e07214e7a7845189699fcf7aa5',
  'ccaa5b655b83f958eb8639e3fe8e6d0a2933b00779f5b84772bec89ba59a31d0',
  '466d4640b64eecc71e8a2dbd3bafdda0118295e07214e7a7845189699fcf7aa5',
  'ccaa5b655b83f958eb8639e3fe8e6d0a2933b00779f5b84772bec89ba59a31d0',
  '7f618537b8994815ac5a2ca347bc13709b7ccd722565832e800c9f824c1f722c',
  'e438ef17a0307ce1b9b42ed3f892f0009027879d21fa70c38175826f981d0eca',
  '82ef9a8178dcb4df0b71540fa06d7da826ecb26e1977e230bdc8c9d6f9f1af84' ]
BAD! no log matches the last!
*/

What do I miss? Thanks for your help

EDIT: added a log for PHP without hex2bin for the key

rekam
  • 1,061
  • 3
  • 13
  • 31
  • I'm not sure but do you really need to convert the key in bin for the hash_mac function of php ? – svgta Sep 01 '22 at 08:37
  • Not using hex2bin give '466d4640b64eecc71e8a2dbd3bafdda0118295e07214e7a7845189699fcf7aa5' on result like the first trace of your node.js log – svgta Sep 01 '22 at 08:42
  • I added a log for PHP script. You see that if I don't hex2bin the key, it doesn't match the expected result. What I want is to find the expected result 82ef9... in nodeJS. – rekam Sep 01 '22 at 09:27
  • Your hex2bin in nodejs must not work as expected – svgta Sep 01 '22 at 09:56

1 Answers1

0

@svgta pointed that the hex2bin function in JS may be broken. I found it somewhere on the web, but it was indeed broken.

Here is the hex2bin function that worked for me (found here https://stackoverflow.com/a/65160900/2030095)

const hex2bin = hex => {
    const length = hex.length / 2;
    const result = new Uint8Array(length);
    for (let i = 0; i < length; i += 1) {
        result[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
    }
    return result;
}
rekam
  • 1,061
  • 3
  • 13
  • 31