AlexR
AlexR

Reputation: 5644

Convert Node.JS code snippet to Javascript (Google Apps Script)

I would like to convert the following Node.JS code snippet to JavaScript in order to run it in Google Apps Script:

From: Node.JS

function getMessageSignature(path, request, nonce) {
  var message   = querystring.stringify(request);
  var secret    = new Buffer(config.secret, 'base64');
  var hash  = new crypto.createHash('sha256');
  var hmac  = new crypto.createHmac('sha512', secret);
  var hash_digest   = hash.update(nonce + message).digest('binary');
  var hmac_digest   = hmac.update(path + hash_digest, 'binary').digest('base64');
  return hmac_digest;
}

This is the code I have tried so far (and many variations of it):

To: JavaScript / Google Apps Script

function getMessageSignature(url, request, nonce) {

  // Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) 
  //and base64 decoded secret API key

  const secretApiKey = 'wdwdKswdKKewe23edeYIvL/GsltsGWbuBXnarcxZfu/9PjFbXl5npg==';
  var secretApiKeyBytes = Utilities.base64Decode(secretApiKey);
  var blob = Utilities.newBlob(secretApiKeyBytes); 
  var secretApiKeyString = blob.getDataAsString(); // POTENTIAL ERROR HERE?

  var json = Utilities.jsonStringify(request); 

  var hash_digest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, 
      nonce + json);

  var hmac_digest = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, 
      url + hash_digest, secretApiKeyString); // POTENTIAL ERROR HERE?

  var base64 = Utilities.base64Encode(hmac_digest);

  return base64;
}

When sending the signature as part of my request to the server, I always get the error message from the server: Invalid Key.

BTW: This is the API which I would like to use in JavaScript: Kraken API

I would appreciate any hint or suggestions very much!!

Upvotes: 5

Views: 4949

Answers (3)

coderofsalvation
coderofsalvation

Reputation: 1803

I noticed this nodejs to GS converter: https://www.npmjs.com/package/codegs

Haven't got the chance to use it, but it claims to handle 'require'-statements.

Upvotes: 2

user8070406
user8070406

Reputation: 41

Solution:

Use jsSHA (https://github.com/Caligatio/jsSHA/) rather than Google App Script's functions. Create a new "jsSHA.gs" code file in Google App Script and copy/past in all the jsSHA optimised .js files from github.

function getKrakenSignature (path, postdata, nonce) {
  var sha256obj = new jsSHA ("SHA-256", "BYTES");
  sha256obj.update (nonce + postdata);
  var hash_digest = sha256obj.getHash ("BYTES");

  var sha512obj = new jsSHA ("SHA-512", "BYTES");
  sha512obj.setHMACKey (api_key_private, "B64");
  sha512obj.update (path);
  sha512obj.update (hash_digest);
  return sha512obj.getHMAC ("B64");
}

function getKrakenBalance () {
  var path = "/0/private/Balance";
  var nonce = new Date () * 1000;
  var postdata = "nonce=" + nonce;

  var signature = getKrakenSignature (path, postdata, nonce);

  var url = api_url + path;
  var options = {
    method: 'post',
    headers: {
      'API-Key': api_key_public,
      'API-Sign': signature
    },
    payload: postdata
  };

  var response = UrlFetchApp.fetch (url, options);

  // ERROR handling

  return response.getContentText ();
}

Upvotes: 4

Paul Draper
Paul Draper

Reputation: 83393

One problem is that querystring.stringify is not the same as Utilities.jsonStringify (which, FYI, is deprecated in favor of JSON.stringify).

I believe that this will be equivalent:

function queryStringify(obj) {
    var params = [];
    for(var key in obj) {
        if(Object.hasOwnProperty(key)) {
           if(typeof key === 'string') {
               params.push([key, obj[key]]);
           } else {
               obj[key].forEach(function(val) {
                   params.push([key, val]);
               });
           }
        }
    }
    return params.map(function(param) {
        return encodeURIComponent(param[0]) + '=' + encodeURIComponent(param[1]);
    }).join('&');
}

Though I am not sure if that is the reason you are seeing your error.

Upvotes: 2

Related Questions