币安API HMAC SHA256签名错误 使用C#

4
我尝试使用C#和RestSharp库连接Binance Api。根据文档,我应该尝试类似于以下内容:
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 我尝试了许多方法并查阅了许多堆栈问题,但我发现其他语言的解决方案并不适用于C#。 这是我基于thisthis完成的。
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();
    }

但我收到了这个错误:此请求的签名无效。我该如何修复它?谢谢。

通常这种故障需要使用不同的填充模式。默认的Net库填充与JSON中的默认填充不同。此外,Net 4.7中的加密问题也很多。当人们从旧版本的Net升级时,代码停止工作。我认为Net中的默认加密模式已更改为与最新的加密模式兼容。 - jdweng
我不知道为什么,但我尝试另一种方法并得到了正确的答案。请参见我的答案@jdweng。 - Sadeq Shajary
1
这个答案解决了我的问题: https://dev59.com/xFYN5IYBdhLWcg3wRmah#47686794 - Sadeq Shajary
2个回答

8
以下是签名生成的工作示例:
    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 是您在查询中传递的参数字符串,例如 timestamp=1586620030079
secret 是您的 API 密钥。

需要注意的重要事项是,在调试步骤中逐步执行时,如果时间戳超出接收窗口,则请求会失败并返回 Bad Request 响应。

您还可以发现此 SDK 至少作为工作代码示例非常有用:https://github.com/nathan-alexander/csharp-binance-api


我刚在我的API中使用了这个。谢谢你。 - Caleb

1
币安已经认识到我们开发者在签名方面遇到的问题,实际上他们已经在他们的代码库这里中添加了一个签名工具。 查看代码并根据您的需求进行调整,如果您按以下方式运行已编译的C#控制台程序:
BinanceDotNet.exe signature

或者像这样:

dotnet run signature

您将获得一个样本签名。

祝您好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接