2

I have been trying to communicate with the private API on kraken. The error I get suggests {"error":["EAPI:Invalid key"]} that the encryption/decryption steps are correct. I have tried creating new keys, does not help. I'm wondering if the 'format' of the signature variable is wrong, even though correct in nature.

function balance () {
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("API_read_only");
    var key = sheet.getRange("B5").getValue()
    var secret = sheet.getRange("B6").getValue()
  
    // (API method, nonce, and POST data)
  
    var path = "/0/private/TradeBalance"
    var nonce = new Date () * 1000
    var postdata = "nonce=" + nonce 
  
    //Algorithms

    //Calculate the SHA256 of the nonce and the POST data 
    // using goolge script lib 
    // using more succint function from https://stackoverflow.com/questions/16216868/get-back-a-string-representation-from-computedigestalgorithm-value-byte
  
    function SHA_256 (str) {
    return Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, str).reduce(function(str,chr){
    chr = (chr < 0 ? chr + 256 : chr).toString(16);
    return str + (chr.length==1?'0':'') + chr;
    },'');
    }
    var api_sha256 = SHA_256(nonce + postdata)

    //Decode the API secret (the private part of the API key) from base64 // need to stringyfy
  
    var base64 = Utilities.base64Decode(secret)
    var base64s = Utilities.newBlob(base64).getDataAsString()
  
//Calculate the HMAC of the URI path and the SHA256, using SHA512 as the HMAC hash and the decoded API secret as the HMAC key
  
    var hamc512_uri = Utilities.computeHmacSha256Signature(path + api_sha256,base64s)
    var hamc512_uris = Utilities.newBlob(hamc512_uri).getDataAsString()
  
//Encode the HMAC into base64
  
    var signature = Utilities.base64Encode(hamc512_uris)
  
    Logger.log(signature)
      
    //An example of the algorithm using the variables shown above is as follows:

    //Base64Encode(HMAC-SHA512 of ("/0/private/TradeBalance" + SHA256("1540973848000nonce=1540973848000&asset=xxbt")) using Base64Decode("FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==") as the HMAC key

  //The result is the API-Sign value / signature.
   
  // connect
  
    var url = "https://api.kraken.com" + path;
    var options = {
    method: 'post',
    headers: {
        'API-Key': key,
        'API-Sign': signature
    },
    payload: postdata
    };

    var response = UrlFetchApp.fetch (url, options);
    json = response.getContentText ();
    
    Logger.log(json)
}
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Robin Le Sage
  • 109
  • 1
  • 5

1 Answers1

0

While I cannot spot what's wrong with your code I faced the same problem as well (thinking I have everything correct but getting a EAPI:Invalid key) with different libraries.

The approach that helped me was:

  • Take some posted working solution, e.g. https://stackoverflow.com/a/43081507/672008 (in Java)
  • Check that it really works
  • Fix the nonce parameter to get a stable HMAC end results
  • Massage my code until I get then same intermediate & end results

In the end I was successful using this library: https://www.npmjs.com/package/jssha

The code:

import jssha from 'jssha';

const secret = '...';
const nonce = 1642383717038;
const message = '';
const path = '/0/private/Balance';
const data = 'nonce=' + nonce;

const dataHash = new jssha('SHA-256', 'TEXT');
dataHash.update(nonce + data + message);

let utf8Encode = new TextEncoder();
const hmacHash = new jssha('SHA-512', 'UINT8ARRAY', { hmacKey: { value: secret, format: 'B64' } });
hmacHash.update(utf8Encode.encode(path));
hmacHash.update(dataHash.getHash('UINT8ARRAY'));

console.log('hmac', hmacHash.getHash('B64'));
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
oae
  • 1,513
  • 1
  • 17
  • 23