1

Given this code in nodejs:

const crypto = require('crypto');
const message = 'message to sign';
const secret = 'mysecret';
const signature = crypto.createHmac('sha256', secret).update(message).digest('hex');
console.log(signature);

The output is 40d4c57eed56968de0f3a22e73ebf8abc6ab4c38bba95fd2c85dd4dc90bf36b9

With the help of the answers here, I have exactly replicated this behavior in Google Apps Script, with this function:

//conversion from byte array taken from: https://stackoverflow.com/a/27933459
function makeHmacSignature(macAlg, message, secret) {
  return Utilities.computeHmacSignature(macAlg, message, secret).reduce(function(str,chr){
    chr = (chr < 0 ? chr + 256 : chr).toString(16);
    return str + (chr.length==1?'0':'') + chr;
  },'');
}

HOWEVER, suppose the signing is changed slightly, such that the secret is a base64 encoded string, and we expect the digest in base64. In the nodejs code, the changes are trivial:

const crypto = require('crypto');
const message = 'message to sign';
const secret = 'mysecret';
const decodedSecret = Buffer(secret, 'base64');
const signature = crypto.createHmac('sha256', decodedSecret).update(message).digest('base64');
console.log(signature);

Giving the output bBLhyGY61BPEbPiFKknX1g9eXv9r98uvwwgVy7YMYDY=

I've been trying for hours, I cannot figure out how to replicate this behavior in Google Apps Script!

delemach
  • 53
  • 1
  • 6

2 Answers2

5

Google Apps Script actually has a utility function for this.

See: https://developers.google.com/apps-script/reference/utilities/utilities#computehmacsha256signaturevalue-key

So instead of

const signature = crypto.createHmac('sha256', secret).update(message).digest('hex');

you could do this:

var byteSignature = Utilities.computeHmacSha256Signature(message, secret);
// convert byte array to hex string
var signature = byteSignature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');
emazzotta
  • 1,649
  • 2
  • 20
  • 29
1

I never successfully figured out how to do this purely with Google Apps Script native functions.

I used jsSHA. I pasted in the optimized sha256.js file, and with that inline, using the example data above, this test function returns the correct output:

function testHmacSigs() {
  var message = 'message to sign';
  var secret = 'mysecret';
  var shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey(secret, "B64");
  shaObj.update(message);
  var sig = shaObj.getHMAC("B64");

  Logger.log(sig);
}
delemach
  • 53
  • 1
  • 6
  • optimised file doesn't exist. is there a better way to find it or get it? Don't know much javascript. – jonathan Apr 11 '20 at 10:35