I’ve been playing around with the Coinbase API, which requires a special “signature” header be included on http requests. This header is comprised of the following elements (per the documentation):

The CB-ACCESS-SIGN header is generated by creating a sha256 HMAC using the secret key on the prehash string timestamp + method + requestPath + body (where + represents string concatenation)

This seemed like a fun challenge so I wrote a little thing in Ruby to create this header.

Notes

  1. Here’s some info on the HMAC standard
  2. this paragraph helped me to understand the reason why HMAC works:
    • HMAC does not encrypt the message. Instead, the message (encrypted or not) must be sent alongside the HMAC hash. Parties with the secret key will hash the message again themselves, and if it is authentic, the received and computed hashes will match.

Ruby has a wrapper around the openssl library which makes this a fairly straightforward process.

Create a file hmac-maker.rb and include the following:

# using ruby 2.2.2
require 'openssl'

key = "YOUR_SECRET_API_KEY_GOES_HERE"

timestamp = ARGV[0]   # number of seconds since Unix Epoch
method = ARGV[1]      # http verb in UPPER CASE
requestPath = ARGV[2] # ex: /v2/accounts
body = ARGV[4] || ""  # defaulted to empty string

data = timestamp + method + requestPath + body

puts OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, data)

Let’s call our script from the terminal and pass it the required values:

ruby hmac-maker.rb $(date +"%s") "GET" "/v2/accounts"

Now we can use this inside a bash curl script to start exploring the API.

touch make-authenticated-request.sh don’t forget the chmod

#!/bin/bash

TIMESTAMP=$(date +"%s")
METHOD=$1
RESOURCE=$2
BODY=${3:-""}
SIGNATURE=$(ruby hmac-maker.rb $TIMESTAMP $METHOD $RESOURCE $BODY)

curl -s -X $METHOD \
  https://api.coinbase.com$RESOURCE \
  -H "cb-access-key: YOUR_ACCESS_KEY" \
  -H "cb-access-sign: $SIGNATURE" \
  -H "cb-access-timestamp: $TIMESTAMP" \
  -H "cb-version: 2017-06-09" \
  -H "content-type: application/json"

usage:

./make-authenticated-request.sh GET "/v2/accounts" | jq