How do I validate the Hmac using NodeJS?
Asked Answered
C

1

6

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);
Countercharge answered 26/6, 2022 at 16:51 Comment(4)
For the verification you have to build the HMAC of the data with the same key again. I.e. the signing and the verifying sides need both, data and key. – Hild
Ah, that's what I was wondering -- stumbled upon that as I was thinking about it. It is quite odd then that the Official NodeJS doc example names that item secret. It should just name that variable key as it does in the definition of the function. thanks for your help. If you write it up as an answer I'll mark it as answer & maybe itll help someone else. πŸ‘πŸ½ – Countercharge
It is secret yes, but not necessarily private. You can share secrets, just not with anybody. And although the key should be randomized, it doesn't need to be random. For instance, you could use key encapsulation (encryption with another key), key agreement and / or key derivation to perform key establishment on both sides. If you think symmetric cryptography like this is problematic then yes, it is, that's why we also have asymmetric cryptography such as RSA and (EC)DH. – Smithsonite
I’m voting to close this question because this question is about not understanding cryptography. Although the poster has undoubtedly learned some valuable lessons, these lessons are in any text about cryptography, and they are not programming related. – Smithsonite
C
10

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.

Countercharge answered 26/6, 2022 at 21:51 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.