C#.NET - 使用HMAC-SHA512签署HTTP POST消息会在某些系统

时间:2018-02-11 16:42:03

标签: c# .net post httpwebrequest hmac

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

为了使用交换机的私有API方法,我必须在http标头中加入一个标志,即POST消息体,使用密钥用HMACSHA512加密。

下面的代码在我的系统中完全正常,但我的一些用户报告说,当服务器尝试使用某些私有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;
    }

1 个答案:

答案 0 :(得分:0)

回答我自己的问题,

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

例如:

double val = 1000.5;

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

取决于格式化将产生 “1000.50000000”或 “1000,50000000”。

因此,在使用Double.ToString方法时必须提供IFormatProvider参数, 或者只是使用像工作一样的肮脏但像工作一样的魅力:

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