How do I validate the Hmac using NodeJS?

Viewed 426

I can successfully create an Hmac via NodeJS using the following code: (slightly altered example from : https://nodejs.org/api/crypto.html#cryptocreatehmacalgorithm-key-options)

Crypto.createHmac('sha256', Crypto.randomBytes(16))
   .update('I love cupcakes')
   .digest('hex');

That results in a value like the following (hex-based string Hmac signature):

fb2937ca821264812d511d68ae06a643915931375633173ba64af9425f2ffd53

How do I use that signature to verify that the data was not altered? (using NodeJS, of course).

My Assumption

I'm assuming there is a method call where you supply the data and the signature and you get a boolean that tells you if the data was altered or not -- or something similar.

Another Solution?

Oh, wait, as I was writing that I started thinking...

Do I need to store the original random bytes I generated (Crypto.randomBytes(16)) and pass them to the receiver so they can just generate the HMac again and verify that the result is the same (fb2937ca821264812d511d68ae06a643915931375633173ba64af9425f2ffd53)?

If that is true that would be odd, because the parameter for Crypto.randomBytes(16) is named secret (in the official example)*. Seems like that needs to be kept secret??

Please let me know if there is a way to verify the signature on the receiving side & how I do that.

Official Documentation : A Bit Confusing

Here's the function as it is defined in the official docs: crypto.createHmac(algorithm, key[, options])

In the function definition, you can see the second param is named key.

However, in the example they refer to it as secret

const secret = 'abcdefg';
const hash = crypto.createHmac('sha256', secret)
               .update('I love cupcakes')
               .digest('hex');
console.log(hash);
1 Answers

Just posting the answer so if anyone in future sees this they will be able to have the definitive answer.

As the commentor (Topaco) pointed out, the simple answer is that:

The receiver who want wants to validate the Hmac simply needs to use the same key value & data and apply it to the method and retrieve the hash value.

const secret = 'abcdefg';
const hash = crypto.createHmac('sha256', secret)
               .update('I love cupcakes')
               .digest('hex');
console.log(hash);

The original Hmac-creating party must provide three things for the verifying party:

  1. data : (could be encrypted data from AES256, for example)
  2. key : original key passed into the createHmac() method -- note: this item is called secret in the sample code by NodeJS (above).
  3. hash :the (clearText) hash which the original creator generated when calling the createHmac() method.

With those three things the verifying party can now call the createHmac() method and determine if the hash they get matches the hash that the original hmac-creating party generated.

Doing this validates that the Data which was sent has not been corrupted or altered.

Additional Note On Key (secret)

I've come back after thinking about the Hmac a bit more. It is required that both parties know the key (aka secret) but it does not mean that it should be exposed to others.

This must be kept secret (as the code implies) because if a nefarious type knew the value and could alter it, then they could also alter the data and generate a new key (secret) and pass it along as if the original creator sent it along (MITM - man in the middle attack).

So, the point here is that yes, both parties have to know the key (secret) value, but it should not be shared where it might be discovered by nefarious types.

Instead, it will have to be agreed upon or based upon a secret password, etc.

Related