Search code examples
javascripthtmlencryptionsha256coinbase-api

sha256 encryption in raw javascript


I'm trying to encrypt a string to HMAC SHA256 within raw javascript using a web-hosted library but it doesn't seem to work. I'm trying to do this to call the Coinbase API. You need to give a few values with the GET request including a Signature, which is where I am experiencing problems. The signature needs to be HMAC SHA256 encrypted. The signature should include the following:

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). The timestamp value is the same as the CB-ACCESS-TIMESTAMP header.

The body is the request body string or omitted if there is no request body (typically for GET requests).

The method should be UPPER CASE.

What I think they are saying is that I can leave out the body because it's a GET request.

My code is the following:

The HTML library call:

<script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.js"></script>

The Javascript Encryption and GET request:

url = "https://api.coinbase.com/v2/accounts"
var xmlHttp1 = new XMLHttpRequest();
xmlHttp1.open( "GET", "https://api.coinbase.com/v2/time", false);
xmlHttp1.send( null )
ts = xmlHttp1.responseText;
var ts1 = JSON.parse(ts)
var message = ts1.data.epoch + "GET" + url + ""
sha256(message);
var hash = sha256.hmac.create('key');

var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", url, false ); // false for synchronous request
xmlHttp.setRequestHeader("CB-ACCESS-KEY", "XXXXXXXXXXXXXXXX");
xmlHttp.setRequestHeader("CB-ACCESS-TIMESTAMP", ts1.data.epoch);
xmlHttp.setRequestHeader("CB-ACCESS-SIGN", hash);
xmlHttp.send( null );

The coinbase API is responding with:

{"errors":[{"id":"authentication_error","message":"invalid signature"}]}

meaning that everything is correct, except for the signature.


Solution

  • I was able to figure it out myself (Yunhai also saw 1 of the problems).

    The problems were:

    • The HMAC encryption needed my API_SECRET

    • I needed to use the URL Parameters, not the entire URL.