6

I've been trying to implement a client for Kraken private API (https://www.kraken.com/help/api) and because I've been running into some issues with that, I've been trying to access that same API with cURL.

However, I can't get for the life of me get it to work and I think I may not be using the right command line tools to generate the hashes and digests.

When accessing the private API the following headers need to be added to the request:

API-Key = «key»
API-Sign = Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded «secret»

On the command line I do the following steps:

  • echo -n "123nonce=123" | openssl sha256

result: (stdin)= 353f9df92ab1d5e5afe06bb7d1bb42a8ef6654b633d94818007aeafbaf03ca3d

  • echo -n "/0/private/Balance353f9df92ab1d5e5afe06bb7d1bb42a8ef6654b633d94818007aeafbaf03ca3d" | openssl sha512 -hmac $(echo -n "wqtzZWNyZXTCuw==" | base64 -d)

result: (stdin)= 6f19f8f058b0e6dc835692840ccdebc1c415f00d42b75b3d3c21ef5fd43f006e30cc9b51c63aba3268a534bf68978d60d2362bffd31c8125553fb8ec41b2f64d

  • echo -n "6f19f8f058b0e6dc835692840ccdebc1c415f00d42b75b3d3c21ef5fd43f006e30cc9b51c63aba3268a534bf68978d60d2362bffd31c8125553fb8ec41b2f64d" | base64

result:

NmYxOWY4ZjA1OGIwZTZkYzgzNTY5Mjg0MGNjZGViYzFjNDE1ZjAwZDQyYjc1YjNkM2MyMWVmNWZk
NDNmMDA2ZTMwY2M5YjUxYzYzYWJhMzI2OGE1MzRiZjY4OTc4ZDYwZDIzNjJiZmZkMzFjODEyNTU1
M2ZiOGVjNDFiMmY2NGQ=
  • curl -X POST -H "Accept: application/json" -H "API-Key: «key»" -H "API-Sign: NmYxOWY4ZjA1OGIwZTZkYzgzNTY5Mjg0MGNjZGViYzFjNDE1ZjAwZDQyYjc1YjNkM2MyMWVmNWZkNDNmMDA2ZTMwY2M5YjUxYzYzYWJhMzI2OGE1MzRiZjY4OTc4ZDYwZDIzNjJiZmZkMzFjODEyNTU1M2ZiOGVjNDFiMmY2NGQ=" -d "nonce=123" https://api.kraken.com/0/private/Balance

result (assuming valid «key» and «secret»): {"error":["EAPI:Invalid signature"]}

But no matter which permutations I try I keep getting the "Invalid signature" error.

These permutations include but are not limited to:

  • Base64 encoding the API-Sign value (all publicly available Kraken clients do this),
  • uppercasing whatever is to be Base64 encoded,
  • leaving out the '/' in front of the URI path,
  • leaving out the actual nonce number at the front of the SHA256.
2
  • 1
    you could try to use one of the working api implementations listed, like the python2 one, and add some debug to see where the difference is.
    – meuh
    Sep 12, 2016 at 16:29
  • Thanks meuh, that made the problem immediately obvious. Kinda silly that I didn't try that before posting my question.
    – aerique
    Sep 13, 2016 at 9:50

1 Answer 1

6

Thanks to meuh I figured out the issue. Since I can imagine other people being as silly as me I'll answer my own question:

The problem is that I'm using strings instead of bytes. I don't have the time to figure it out for the command line and cURL (perhaps someone else wants to do that and I'll accept that answer).

For the client I was working on, instead of concatenating /0/private/Balance and the SHA256 hex string 353f9df92ab1d5e5afe06bb7d1bb42a8ef6654b633d94818007aeafbaf03ca3d I should concatenate the bytes for "/0/private/Balance" (47 48 47 112 114 105 118 97 116 101 47 66 97 108 97 110 99 101) and SHA256("123nonce=123") (53 63 157 249 42 177 213 229 175 224 107 183 209 187 66 168 239 102 84 182 51 217 72 24 0 122 234 251 175 3 202 61) (shown as decimal values this time).

Same for the SHA512 HMAC.

Edit:

Since someone asked on Twitter, these are the actual steps to do it on the commandline:

  1. echo -n "/0/private/Balance" > tmp.bin
  2. echo -n "123nonce=123" | openssl sha256 -binary >> tmp.bin
  3. cat tmp.bin | openssl sha512 -binary -hmac $(echo -n "wqtzZWNyZXTCuw==" | base64 -d) | base64 ("wqtzZWNyZXTCuw==" is "«secret»" BASE64 encoded, this should ofcourse be your secret)
  4. curl -X POST -H "Accept: application/json" -H "API-Key: «key»" -H "API-Sign: «output-from-step-3»" -d "nonce=123" https://api.kraken.com/0/private/Balance

As you can seen above, the one thing that was forgotten in the original question was using the -binary switch.

Note: your API key and secret will end up on the commandline (visible with ps aux) and in your shell history!

2
  • This solution is perfect, but I needed to add a -w 0 after the second base64 to avoid splitting the output in two (without -w, the output is formated in two columns of 76 characters). You also forgot a $ sign before the parenthesis. Final command for line 3: cat tmp.bin | openssl sha512 -binary -hmac $(echo -n "wqtzZWNyZXTCuw==" | base64 -d) | base64 -w 0
    – mountrix
    Jul 22, 2017 at 11:12
  • The forgotten $ sign is because I use the fish shell. I should have assumed Bourne shell, sorry.
    – aerique
    Jul 23, 2017 at 13:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .