Bitmymoney 'API key registration' REST API

Introduction

This document describes how to generate and register an API key to the bitmymoney.com website. API keys can be used to authenticate to bitmymoney.com when using its REST API.

Generating a key

Use any library to generate an ECDSA private key and its public counterpart, make sure to use the secp256k1 curve (same as used for Bitcoin signatures) to generate the key, and use SHA256 as the hashing mechanism. Be sure sufficiently random data is used and that the private key is stored safely.

Since the process is very different depending on environment and libraries used, only a very high level example is provided (mostly to verify the results of converting a string to a private key, and a private to a public key) using a very simple (non-public) library:

>>> import ecdsasig
>>> private_key = ecdsasig.privkey_from_seed('foobar')
>>> private_key
82515686765357280375972673969881645280600095682959160169906331085635234308592L
>>> ecdsasig.pubkey_from_privkey(private_key)
'83e70f8d7eaf6dfa34a1ed1c0624051686c635c69134f4885e6b9c1f763ed8d7a8a6c54b5f0c05321b94a48c8fef489fc698b94c3b9982a9f69d1de6765cbe02'

Registering a key

Keys can be registered using the /user/apikey/register/ URL described in the API documentation. This URL accepts a hex serialization of the public key, along with information about the user and client, and returns a structure containing, among other things, a 'key id' which is used to identify the key on the server. This key id needs to be stored and used, along with the private key, to generate signature headers later.

Signing a request

Signing a request involves generating a nonce higher than the previous one, then stringifying the nonce and concatenating (without separator) the key id as provided by the server, the raw URI and the request body (if available, else ''), and then using the ECDSA private key to sign that concatenated string. The binary result should be converted to a lower-case hexadecimal string of 128 characters long.

An example, let's say the private key from seed 'foobar' as generated in the example code above is uploaded to the server (see URL descriptions below) and the server has stored it under key id '00000000' (this would have been returned in the POST response, as described below), we would sign a request to URL 'https://www.bitmymoney.com/account/123/' with request body 'spam=eggs' and nonce 1234 as follows:

>>> sign = ecdsasig.sign(
...   private_key,
...  '123400000000https://www.bitmymoney.com/account/123/spam=eggs')
>>> sign.encode('hex')
'2ee2c88aaef1db9cad7b05f78ab78b88ffd3cde3fc1d44b2e1c21485d6dcd6e14d813d765014028d08583e28a7cc63b01f1c237bcf7e80fe188fa9606f6f930e'

The produced hex string can be used in the HTTP Authorization header.

HTTP header format

The format of the HTTP header is as follows:

Authorization: Biccur-ECDSA key="<keyid>", nonce="<nonce>", sign="<sign>"

where <keyid> is the key id as returned by the register URL, <nonce> is a integer higher than any previously used nonce (or higher than 0 for the first use) and <sign> is a signature of the request data (nonce + key id + uri + raw body data, see code example above).

NOTE: Previously a colon : had to be added after the Biccur-ECDSA auth type bit in the header, this requirement has been removed to be more consistent with other auth types (e.g. Basic). The colon will be supported for now, but we advise against adding it.

Response signatures

On registration, a server-generated public key is returned along with the registration information. This should be used to verify if responses are unmodified. The server generates a signature using the same mechanism as described above from the response data, without the url (so data consists of nonce + key id + raw response body) and stores the results in a header called X-Biccur-ECDSA-Response-Sign. It is highly advised to check the validity of this signature on the client!