6

I am playing around implementing an API. Usually that is really simple, but this one gives me problems. However, I am pretty sure the problem is me, and not the API.

Url to this specific API:

https://www.bitstamp.net/api/

I want to make POST call to the "Account balance". Currently I get the following answer:

{"error": "Missing key, signature and nonce parameters"}

and I try to do it with the following code:

        var path = "https://www.bitstamp.net/api/user_transactions";
        var nonce = GetNonce();
        var signature = GetSignature(nonce);

        using (WebClient client = new WebClient())
        {

            byte[] response = client.UploadValues(path, new NameValueCollection()
           {
               { "key", Constants.ThirdParty.BitStamp.ApiKey },
               { "signature", signature },
               { "nonce", nonce},

           });
            var str = System.Text.Encoding.Default.GetString(response);
        }

        return 0.0m;

This is my two helper functions:

    private string GetSignature(int nonce)
    {
        string msg = string.Format("{0}{1}{2}", nonce,
            Constants.ThirdParty.BitStamp.ClientId,
            Constants.ThirdParty.BitStamp.ApiKey);

        return HelperFunctions.sign(Constants.ThirdParty.BitStamp.ApiSecret, msg);
    }

    public static int GetNonce()
    {
        return (int) (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
    }

My crypto sign function is this one:

    public static String sign(String key, String stringToSign)
    {
        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

        byte[] keyByte = encoding.GetBytes(key);
        HMACSHA256 hmacsha256 = new HMACSHA256(keyByte);

        return Convert.ToBase64String(hmacsha256.ComputeHash(encoding.GetBytes(stringToSign)));
    }

Any idea why i get the "missing key" error? Is there something obvious I am doing wrong (probably is :) )?

Edit:

Fiddler tells me I post the following data:

key=mykeymykey&signature=PwhdkSek6GP%2br%2bdd%2bS5aU1MryXgrfOD4fLH05D7%2fRLQ%3d&nonce=1382299103%2c21055

Edit #2:

Updated code on generating the signature:

private string GetSignature(int nonce)
    {
        string msg = string.Format("{0}{1}{2}", nonce,
            Constants.ThirdParty.BitStamp.ClientId,
            Constants.ThirdParty.BitStamp.ApiKey);

        return HelperFunctions.ByteArrayToString(HelperFunctions.SignHMACSHA256(
            Constants.ThirdParty.BitStamp.ApiSecret, msg)).ToUpper();
    }
public static byte[] SignHMACSHA256(String key, byte[] data)
{
    HMACSHA256 hashMaker = new HMACSHA256(Encoding.ASCII.GetBytes(key));
    return hashMaker.ComputeHash(data);
}

public static byte[] StrinToByteArray(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

public static string ByteArrayToString(byte[] ba)
{
    return BitConverter.ToString(ba).Replace("-", "");
}
Lars Holdgaard
  • 9,496
  • 26
  • 102
  • 182

1 Answers1

4

I think that the problem is that you are using base64 (Convert.ToBase64String), but in the relevant section of the API docs, it is written:

Signature is a HMAC-SHA256 encoded message containing: nonce, client ID and API key. The HMAC-SHA256 code must be generated using a secret key that was generated with your API key. This code must be converted to it's hexadecimal representation (64 uppercase characters).

So you have to convert the byte array to a hexadecimal string. See this question to get some examples of how to do it.

Community
  • 1
  • 1
astrada
  • 773
  • 5
  • 14
  • Thanks a lot for your proposal. Simply didn't fix the error :-) – Lars Holdgaard Oct 25 '13 at 21:40
  • 4
    I made a test, and I found that the problem is the URL you are using. If you make a POST to `https://www.bitstamp.net/api/user_transactions`, you get redirected to `https://www.bitstamp.net/api/user_transactions/` (note the final slash). `WebClient` follows redirect automatically, but does not reupload values. You should try to POST to the URL with the ending slash. – astrada Oct 28 '13 at 09:19
  • That helped sooooo much! I finally got a new error, which I can actually use! Thanks, thanks, thanks :) – Lars Holdgaard Oct 28 '13 at 21:53