The purpose of this post is to document how I used the built-in key-Hashed Message Authentication Code (HMAC) scheme in Ruby to sign HTTP requests.
I recently wrote a Ruby Gem that acts as an API wrapper for the Kraken Digital Asset Trading Platform.
The Kraken API allows users to query public market data without an API Key. However, in order to query private user data or make trades through the API, a user must use their API Key and API Secret to sign any requests to the site.
The signature scheme required by Kraken is as follows:
POST Header must have:
POST Body must contain:
Ok, so what does all of this stuff mean?:
API-Key: Provided by Kraken to a user
API-Sign: This is the hard part and the main topic of this post, but basically, this proves that the POST request is being sent by the owner of the account and that the request has not been tampered with by a MITM.
otp: One time password, required if two factor authentication is enabled on account (we will assume 2-factor auth is not enabled).
Now, let’s look at how we can generate a nonce and the proper signature using Ruby.
First the nonce:
This method generates a timestamp and pads it with zeros so that it is always a 64 bit “stringified” number. A timestamp does not have to be used, but the nonce must increase after each request and the properties of time give us an easy way to ensure this incrementation occurs.
Next, the signature code. Skim it and then read the step by step description below. This code snippet is taken from the full gem.
This is a lot, so let’s break it down.
The code above takes an API
method, such as
'QueryTrades' and any related options (which aren’t always required for this API).
Line 7 adds the
nonce to the
Line 8 encodes the
nonce included) to put into the body of the HTTP request. The output looks something like
"nonce=1094093234000000". If there were additional options, they would be included in this string and separated by a
addressable Ruby Gem is being used to do the encoding.
headers hash on line 10 has two values:
API-Key is defined by the user.
API-Sign, on the other hand, needs to be calculated.
generate_signature method takes as input the API
method, such as
'Balance', the previously encoded
post_data, and the
opts hash with our
The API Secret given by Kraken is Base64 encoded, so we call the
Base64.decode64 method to decode the key before we generate our signature.
generate_message method generates the message that we will sign in the HMAC. This message, as detailed by Kraken, must contain
URI path + SHA256(nonce + POST data). Line 37 generates the SHA256 hash (with binary output - as opposed to hexdigest). Line 38 appends this to our path.
Now that we have the
message, we can finally generate the HMAC. The
generate_hmac method uses the
OpenSSL::HMAC.digest method built into Ruby. It takes as input the cryptographic hash function you wish to use for the signature (SHA512 in our case), the decoded API-Secret
key and the
message you wish to sign.
IMPORTANT: We then
join the signature to remove a “/n” (newline) character that
Base64.encode64 inserts into the signature.
It took me quite a while to figure out that this happened. Apparently, the
Base64.encode64 method inserts a newline after every 60 characters. I just read that there is a
Base64.strict_encode64 method that doesn’t do this. I will update this post once I dig more into that.
The rest of the
post_private method isn’t as interesting. It composes the HTTP POST request using the
HTTParty gem and returns the parsed response.
Full stop. That is enough for one blog post!