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.

Nonce: This is short for “number used once" and is used to protect against replay attacks.

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 'Balance' or 'QueryTrades' and any related options (which aren’t always required for this API).

Line 7 adds the nonce to the options hash.

Line 8 encodes the options (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 &. The addressable Ruby Gem is being used to do the encoding.

The 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.

The generate_signature method takes as input the API method, such as 'Balance', the previously encoded post_data, and the opts hash with our nonce value.

The API Secret given by Kraken is Base64 encoded, so we call theBase64.decode64 method to decode the key before we generate our signature.

The 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 split and 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!