Search code examples
node.jsencodingcryptographyhmacnode-crypto

crypto createHMAC output differs according to nodejs version


I have issues with crypto module while upgrading my node version. The created HMAC depends on the version of node. You'll find below the piece of code that reproduces the problem.

If I encode my key as BASE64 (or any) the HMAC does not depends on node.js version.

If I encode it as binary, the HMAC is different if I change my node.js version.

[EDIT] according to Why crypto.createHash returns different output in new version? I have added the encoding when calling the update function

code snippet

"use strict";

const crypto = require('crypto');

console.log(process.version);

let key = '5ece799aa73a7a8e687876f8e0eabe2e200b967ef5728d845f72fc9ea27dbcd90cd4e06e8bc90d823ac8a54ce91f68ca37fc2e7bbf3f5ef9d82b4c6b938f1936';

let _key64 = (new Buffer(key, 'hex')).toString('base64');
console.log("B64 KEY: "+crypto.createHmac('sha512', _key64).update("hey", "binary").digest('hex').toUpperCase());

let _keyBin = (new Buffer(key, 'hex')).toString('binary');
console.log("BIN KEY: "+crypto.createHmac('sha512', _keyBin).update("hey", "binary").digest('hex').toUpperCase());

The output is the following with 2 versions of node.js

v5.6.0
B64 KEY: 0DC11C737E575B17DD575042F8F372E3D63A86C3B56C06FB74C9B0AB8E96A5FC8A2DC33667280DC5B306C93AA3DECBAF0D8EDE56F3666C11BFC25A70CFC027D0
BIN KEY: E5A9F813D9AA64A6791BEA91035553FFC730DBE635D0CE7AC722C0195DFDD77A969323FDDFB4E5054E59073DAE9B9BF00CFF73CF20F2FACEE01F79F25E7B9303
v8.1.4
B64 KEY: 0DC11C737E575B17DD575042F8F372E3D63A86C3B56C06FB74C9B0AB8E96A5FC8A2DC33667280DC5B306C93AA3DECBAF0D8EDE56F3666C11BFC25A70CFC027D0
BIN KEY: 6F089BCA7A24BF6C3F8E0F75349C8B446C4E69336CF41AA7A390C9B17086417E475545197B0312B4D9240A9F0388CA8722ADCF04BFD554321290EBBCD61F800E

note: this is a narrowing of this question: HMAC changes according to node version (paybox module)

By the way, If I do

const key = '5ece799aa73a7a8e687876f8e0eabe2e200b967ef5728d845f72fc9ea27dbcd90cd4e06e8bc90d823ac8a54ce91f68ca37fc2e7bbf3f5ef9d82b4c6b938f1936'
const bkey = (new Buffer(key, 'hex')).toString('binary');
console.log((new Buffer(bkey, 'binary')).toString('hex'));

no problem, I obtain the same key 5ece799aa73a7a8e687... whatever the version of node.


Solution

  • Solved thanks to @matt: To sum up his comment

    Because of https://github.com/nodejs/node/commit/b010c8716498dca398e61c388859fea92296feb3, it is preferable to pass the buffer to crypto, by removing .toString('binary')

    So this

    "use strict";
    
    const crypto = require('crypto');
    
    console.log(process.version);
    let key = '5ece799aa73a7a8e687876f8e0eabe2e200b967ef5728d845f72fc9ea27dbcd90cd4e06e8bc90d823ac8a54ce91f68ca37fc2e7bbf3f5ef9d82b4c6b938f1936';
    
    let _key64 = (new Buffer(key, 'hex')).toString('base64');
    console.log("B64 KEY: "+crypto.createHmac('sha512', _key64).update("hey", "binary").digest('hex').toUpperCase());
    
    let _keyBin = (new Buffer(key, 'hex'));
    console.log("BIN KEY: "+crypto.createHmac('sha512', _keyBin).update("hey", "binary").digest('hex').toUpperCase());
    

    works (of course)

    v5.6.0
    B64 KEY: 0DC11C737E575B17DD575042F8F372E3D63A86C3B56C06FB74C9B0AB8E96A5FC8A2DC33667280DC5B306C93AA3DECBAF0D8EDE56F3666C11BFC25A70CFC027D0
    BIN KEY: E5A9F813D9AA64A6791BEA91035553FFC730DBE635D0CE7AC722C0195DFDD77A969323FDDFB4E5054E59073DAE9B9BF00CFF73CF20F2FACEE01F79F25E7B9303
    v8.1.4
    B64 KEY: 0DC11C737E575B17DD575042F8F372E3D63A86C3B56C06FB74C9B0AB8E96A5FC8A2DC33667280DC5B306C93AA3DECBAF0D8EDE56F3666C11BFC25A70CFC027D0
    BIN KEY: E5A9F813D9AA64A6791BEA91035553FFC730DBE635D0CE7AC722C0195DFDD77A969323FDDFB4E5054E59073DAE9B9BF00CFF73CF20F2FACEE01F79F25E7B9303