2

I currently have this snippet in Python -

import base64
import hashlib
import hmac
def hash_hmac(self, key, data):
    res = hmac.new(base64.b64decode(key), data.encode(), hashlib.sha512).digest()
    return res

I am trying to replicate it in Node.js, but having difficulty getting the correct hash.

const crypto = require('crypto')
const hashHmac = (key, message) => {
  return crypto.createHmac('sha512', Buffer.from(key, 'base64').toString('utf-8'))
        .update(message)
        .digest()
        .toString('base64') 
}

Test case: Key: '7pgj8Dm6' Message: 'Test\0Message'

With the python snippet, the hash is

69H45OZkKcmR9LOszbajUUPGkGT8IqasGPAWqW/1stGC2Mex2qhIB6aDbuoy7eGfMsaZiU8Y0lO3mQxlsWNPrw==

With the js snippet, the hash is

OhaJU9IibhhjIjz3R7FmodgOBUPjwhndXX8gn0r2rRzjQvCJl4T40rHXKw3o6Y2JQ5fVHTeStu8K1DRMWxMGBg==

Am I going wrong with the base64 encoding?

3
  • 1
    In the NodeJS code replace Buffer.from(key, 'base64').toString('utf-8') with Buffer.from(key, 'base64'). The UTF-8 decoding corrupts the data. Commented Jul 2, 2021 at 6:15
  • Awesome it worked!, can you answer it so I can accept it :) Commented Jul 2, 2021 at 7:03
  • Sure. I posted my comment as an answer. Commented Jul 2, 2021 at 7:47

2 Answers 2

3

In the NodeJS code, the key is first Base64 decoded and then UTF-8 decoded. Since the key contains byte sequences that are not defined by UTF-8, it is thereby damaged.

Arbitrary binary data, such as ciphertexts, hashes, or keys (at least if randomly generated), must be stored in binary, or a binary-to-text encoding like Base64 must be used (and not a character set encoding like UTF-8) if they are to be converted to a string, see also here.

In the posted example, converting the buffer to a string is not necessary at all. The key can simply be passed directly as a buffer, s. crypto.createHmac(), i.e. as follows:

var hmac = crypto.createHmac('sha512', Buffer.from(key, 'base64'));

With this, the NodeJS code returns the same result as the Python code.

Sign up to request clarification or add additional context in comments.

Comments

0

If you installed NodeJs:

 echo "console.log(require('crypto').createHmac('sha512', 'nonbase64key').update('password').digest('hex'))" | node

it's equivalent in python is:

python3 -c 'import hashlib;import base64;import hmac;print(hmac.new(b"nonbase64key", "password".encode(), hashlib.sha512).hexdigest())'

And the equivalent pure shell command is:

echo -n "password" | openssl sha512 -hmac "nonbase64key"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.