Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HMAC in Node.js crypto vs. Google Apps Script (GAS)

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?

like image 487
Tomáš Klíma Avatar asked May 21 '15 09:05

Tomáš Klíma


1 Answers

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.

var secret = Utilities.base64Decode(key);
secret = Utilities.newBlob(secret).getDataAsString();

Try this example. I replaced your key with a new base64 encoded string and converted b64-decoded outputs to strings:
In node:

var key = "VEhJUyBJUyBBIFNUUklORw==";
//var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw==";
var secret = new Buffer(key, "base64").toString();
var message = "message";
var crypto = require("crypto");
var hmac = new crypto.createHmac("sha512", secret);
var signature = hmac.update(message).digest("base64");
console.log(signature);

In GAS:

//var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw==";
var key = "VEhJUyBJUyBBIFNUUklORw=="
var message = "message";
var secret = Utilities.base64Decode(key);
secret = Utilities.newBlob(secret).getDataAsString();
var hmac = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret);
var signature = Utilities.base64Encode(hmac);
Logger.log(signature);

both return the signature:

a9Jk2YQsKC164zEUoVChIpyfnEUZLj+Sj1mCAqs+jhDFvOliTupIfV+D6CNtaQGhQvAO40FZLhvYGubt1R5jQA==

But if I put your key back in the signatures again stop matching.

like image 111
Spencer Easton Avatar answered Oct 26 '22 00:10

Spencer Easton