4

I try to connect to the Binance Api Using C# And RestSharp lib. Based on documents I should try something like this:

queryString: symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

HMAC SHA256 signature:

[linux]$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j" (stdin)= c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71 curl command:

(HMAC SHA256) [linux]$ curl -H "X-MBX-APIKEY: vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A" -X POST https://api.binance.com/api/v3/order?symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71

I try many ways and many stack questions but I found solutions for other languages not c#. this i I done based on: this and this

public string GetAccountInfo()
    {
        long timeStamp = GetTimestamp();
        var request = new RestRequest("api/v3/account");
        request.AddHeader("X-MBX-APIKEY", ApiKey);
        request.AddParameter("timestamp", timeStamp, ParameterType.QueryString);
        request.AddParameter("recvWindow", RecvWindow, ParameterType.QueryString);
        request.AddParameter("signature", GetSignature(request.Parameters), ParameterType.QueryString);
        return Client.Get(request).Content;
    }
private long GetTimestamp()
    {
        return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
    }

    private string GetSignature(List<Parameter> parameters)
    {
        var signature = "";
        if(parameters.Count > 0)
        {
            foreach (var item in parameters)
            {
                if(item.Name != "X-MBX-APIKEY")
                    signature += $"{item.Name}={item.Value}&";
            }
            signature = signature.Substring(0, signature.Length - 2);
        }
        byte[] keyBytes = Encoding.Unicode.GetBytes(ApiSecret);
        byte[] valueBytes = Encoding.Unicode.GetBytes(signature);
        return HashEncode(HashHMAC(keyBytes, valueBytes));
    }

    private static byte[] HashHMAC(byte[] key, byte[] message)
    {
        var hash = new HMACSHA256(key);
        return hash.ComputeHash(message);
    }

    private static string HashEncode(byte[] hash)
    {
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }

but I got this error: Signature for this request is not valid. How can I fix it? Thank you.

Sadeq Shajary
  • 351
  • 3
  • 10
  • Usually failures like this require a different padding mode. The default Net library padding is different from the default in JSON. Also a lot of issues have been occurring with encryption in Net 4.7. When people have been upgrading from older Net the code stopped working. I think the default encryption modes have changed in Net to be compatible with latest encryption modes. – jdweng Mar 28 '20 at 10:50
  • I don't know why exactly but I try another way and got a correct answer. see my answer @jdweng – Sadeq Shajary Mar 28 '20 at 11:01
  • 1
    This Answer resolve my problem: [https://stackoverflow.com/a/47686794](https://stackoverflow.com/a/47686794) – Sadeq Shajary Mar 28 '20 at 11:01

2 Answers2

8

Below is the working example of signature generation:

    public static string CreateSignature(string queryString, string secret)
    {

        byte[] keyBytes = Encoding.UTF8.GetBytes(secret);
        byte[] queryStringBytes = Encoding.UTF8.GetBytes(queryString);
        HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes);

        byte[] bytes = hmacsha256.ComputeHash(queryStringBytes);

        return BitConverter.ToString(bytes).Replace("-", "").ToLower();
    }

queryString is your string of parameters passed in query, e.g. timestamp=1586620030079
secret is your api secret.

Important thing to note is that request fails with Bad Request response when you go in debug step by step because timestamp gets outside of recv window.

You could also find this SDK very useful at least as working code example: https://github.com/nathan-alexander/csharp-binance-api

xalien
  • 153
  • 1
  • 7
1

Binance has acknowlegded the problems us developers have with signatures, as a matter of fact they have added a signature utility to their repo here. Check out the code and adjust it to your needs, if you run the compiled C# console program like this:

BinanceDotNet.exe signature

Or like this:

dotnet run signature

You'll get a sample signature.

Best of luck