Can you anybody explain me a difference between creating HmacSha512 signature using Crypto module of Node.JS and Google Apps Script?
Code 1 - Node.JS
var secret = "my secret";
var message = "message";
var crypto = require("crypto");
var hmac = new crypto.createHmac("sha512", secret);
var signature = hmac.update(message).digest("base64");
console.log(signature);
Code 1 - Google Apps Script
var secret = "my secret";
var message = "message";
var signature = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret));
Logger.log(signature);
Both of codes generate identical signature:
g4fZkM2XGNjhti9Wah3TU2/rvmxbL3nk4F3ZLljpED23oQ7Y7dtVmVKprQKuzyt0B4Spo214isWCvnoXXVTS8g==
But the problem comes when we have the secret in the form of base64 encoded key. So, first step we have to do is prepare the secret. Let's modify the code:
Code 2 - Node.JS
var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw==";
var secret = new Buffer(key, "base64");
var message = "message";
var crypto = require("crypto");
var hmac = new crypto.createHmac("sha512", secret);
var signature = hmac.update(message).digest("base64");
console.log(signature);
The result:
GELSKf33zit7nIfjj8XH3wZIga/CSYuCU5oTGysqOg6C/wFggunw59wzc7Mr95XW/gZ8putB67AADqnP0gLdiw==
Code 2 - Google Apps Script
var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw==";
var message = "message";
var secret = Utilities.base64Decode(key);
var signature = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret));
Logger.log(signature);
The result:
l11xAQ5C5ARx/r/pbNYpMKCqWOwIaxFTkfS9OXCwfUxv33y3gU/sL2vHueOxpkCKmF+lxIcFMYblwrvfWaTZkg==
The difference is probably in processing/decoding the key (Buffer vs. Utilities.base64Decode. The Node.js version is the right (it's verified against to server-side).
How to correctly decode and use the key using Google Apps Script?
Aditional findings:
The results are the same form both of codes when it is used another key - as Spencer wrote. But there is yet another strange thing. Let's use Spencer's key to be sure both of codes will work. When we want to sign message with non-ASCII characters, e.g. "Tomáš", the codes will produce different results too!
Utilities.base64Decode() returns a byte array not a string. You can create a blob from the byte array and then get it as a string restoring the original encoded string.
Try this example. I replaced your key with a new base64 encoded string and converted b64-decoded outputs to strings:
In node:
In GAS:
both return the signature:
But if I put your key back in the signatures again stop matching.