C#.NET - 使用 HMAC-SHA512 签名 HTTP POST 消息在某些系统中会产生不一致的结果

标签 c# .net post httpwebrequest hmac

我正在构建一个程序,与加密货币交易所的 API 交互以下达买入/卖出订单等。

为了使用交易所的私有(private) API 方法,我必须在 http header 中包含一个标志,即 POST 消息正文,并使用 key 使用 HMACSHA512 进行加密。

下面的代码在我的系统中运行得很好,但我的一些用户报告说,当他们尝试使用某些私有(private) API 方法时,服务器总是返回签名错误。

我尝试在多个系统设置中重现该错误,但无济于事。

我想知道下面的代码的任何部分在不同的系统设置中使用时是否容易出现不一致。

    public string SendQuery(string apiKey, string secretKey, string method, string[] param, string url)
    {
        // nonce
        string nonceStr = Utility.CurrentTimeMillis().ToString() + "0000000000";

        // generate the POST message
        string postString = "method=" + method + "&nonce=" + nonceStr;
        if (param != null) 
        {
            foreach (string item in param) postString += "&" + item;
        }            
        byte[] postData = Encoding.ASCII.GetBytes(postString);

        // sign POST message
        HMACSHA512 hMACSHA512 = new HMACSHA512(Encoding.ASCII.GetBytes(secretKey));
        byte[] sign = hMACSHA512.ComputeHash(postData);
        string signString = string.Empty;
        for (int i = 0; i < sign.Length; i++)
        {
            signString += sign[i].ToString("X2");
        }
        signString = signString.ToLower();   // must use lower case

        // generate headers
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Headers.Add("Key", apiKey);
        request.Headers.Add("Sign", signString);
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = postData.Length;
        request.KeepAlive = true;
        request.Proxy = null;
        request.Method = "POST";
        request.Timeout = 5000;

        string message = string.Empty;

        try
        {
            using (Stream st = request.GetRequestStream())
                st.Write(postData, 0, postData.Length);

            Stream responseStream = request.GetResponse().GetResponseStream();
            StreamReader objReader = new StreamReader(responseStream);

            string line = "";

            while (line != null)
            {
                line = objReader.ReadLine();
                if (line != null) message += line;
            }
        }
        catch (Exception ex)
        {

        }

        return message;
    }

最佳答案

所以回答我自己的问题,

事实证明,问题并不在于我的 SendQuery 方法中,而是调用它的函数使用 Double.ToString("F8") 来生成参数值,这会导致小数分隔符字符根据本地格式而变化。

例如:

double val = 1000.5;

string str = val.ToString("F8");

根据格式的不同,会产生 “1000.50000000”或 “1000,50000000”。

因此,在使用 Double.ToString 方法时,您必须提供 IFormatProvider 参数, 或者只是使用一个肮脏但有效的技巧,例如:

ToString("F8").Replace(",", ".");

关于C#.NET - 使用 HMAC-SHA512 签名 HTTP POST 消息在某些系统中会产生不一致的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48733839/

相关文章:

c# - 带有 MySql 的 Log4net 不记录

c# - 调整矩形数组的大小

c# - 如何在不断检查进度的同时在 ASP.NET 4 中异步加载页面?

c# - 遗漏一个字母和两个倒序字母的单词的正则表达式

C# TCP 套接字编程 - 确定连接是否已断开

c# - IDbConnection 和 Firebird

bash - 将带有空格的变量扩展为 curl POST 变量

json - 无法在 swift 4 中发出 post 请求

javascript - 是否有可能在发布之前重命名 html 文件输入的文件

c# - 您最喜欢阅读 XML 文件的方式是什么?