How to use CryptoJS package in Postman Flows Evaluate block

How can we use evaluate block in postman flows to validate the hmac signed payload. I’m using the below code

const crypto = require('crypto'); 
const secret = 'mySecretKey'; 
const payload = request.body; 
console.log(payload);
const receivedHmac = payload;
const data = JSON.stringify(payload); 
const generatedHmac = crypto.createHmac('sha256', secret).update(data).digest('hex');
if (receivedHmac === generatedHmac) { 
    console.log('Payload is valid'); 
    } else {
         console.log('Payload is not valid'); 
    }

This is throwing me an error invalid redefinition of global identifier.

“data” is a reserved variable, so I would change that to something else.

Hi @avionics-specialist3

We support the web crypto API in the evaluate block.

Try the below code:

const secret = 'mySecretKey';
const payload = request.body; 
console.log(payload);
const receivedHmac = 'expected_hmac_here'; 

const encoder = new TextEncoder();
const data = encoder.encode(payload)
  crypto.subtle.importKey('raw', new TextEncoder().encode(secret), {
    name: 'HMAC',
    hash: 'SHA-256',
  }, false, ['sign'])
    .then((key) => crypto.subtle.sign('HMAC', key, data))
    .then((signature) => {
      const generatedHmac = Array.from(new Uint8Array(signature)).map(byte => byte.toString(16).padStart(2, '0')).join('');
      return generatedHmac === receivedHmac;
    })
    .catch((error) => {return error});

If you want a constant time comparison function to compare the HMACs, you can use this function:

function constantTimeCompare(str1: string, str2: string): boolean {
    if (str1.length !== str2.length) {
        return false;
    }

    let result = 0;
    for (let i = 0; i < str1.length; i++) {
        result |= str1.charCodeAt(i) ^ str2.charCodeAt(i);
    }

    return result === 0;
}
constantTimeCompare(receivedHmac, generatedHmac)

The error you’re receiving in your code is in reference to trying to import the crypto library.

1 Like

Hi Daniel,

I am trying to verify signing keys in Postman. I was able to do this using CryptoJs:

const CryptoJS = require('crypto-js');
pm.test('JWT Signature is Valid', function () {
    let recreatedSignature;
    try {
        // Generate the hash using HMAC-SHA256 and encode to Base64
        recreatedSignature = CryptoJS.HmacSHA256(
                `${jwtHeaderEncoded}.${jwtPayloadEncoded}`,
                jwtSigningKey
            )
            .toString(CryptoJS.enc.Base64)
            .replace(/=*$/, '');
        console.log('recreatedSignature', recreatedSignature);
    }
    catch(e) {
        throw new Error('Could not recreate signature | ' + e)
    }
    
    pm.expect(jwtSignature).to.be.a('string').that.equals(recreatedSignature);
});

However, require('crypto-js'); does not work for Newman tests, so I am trying to convert this to a Newman-friendly format.

I have not been able to implement this with your solution (modified for my purposes):

pm.test('JWT Signature is Valid', function () {
    let recreatedSignature;
    try {
        const encoder = new TextEncoder();
        const data = encoder.encode(`${jwtHeaderEncoded}.${jwtPayloadEncoded}`)
        crypto.subtle.importKey('raw', new TextEncoder().encode(jwtSigningKey), {
            name: 'HMAC',
            hash: 'SHA-256',
        }, false, ['sign'])
            .then((key) => crypto.subtle.sign('HMAC', key, data))
            .then((signature) => {
                recreatedSignature = _arrayBufferToBase64(signature);
                pm.expect(jwtSignature).to.be.a('string').that.equals(recreatedSignature);
            })
            .catch((error) => {console.log(error)});
    }
    catch(e) {
        throw new Error('Could not recreate signature | ' + e)
    }
});
// https://stackoverflow.com/a/9458996/27294094
function _arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return btoa( binary );
}

Furthermore, it looks like the Promise flow breaks the Chai tests - where it reports test success even when there is a failure.

Hi @matthew-beck-cpc

Can you make this question a new post tagged with Newman since it isn’t about flows? It’s not my area of expertise but i’m sure the experts there will be able to help you :slight_smile:

1 Like