HMAC - C#和JavaScript给出了不同的结果

时间:2018-03-21 13:14:34

标签: javascript c# security hmac

我的问题类似于HMAC C# and JavaScript,但由于问题缺乏一些细节,答案不是很有帮助,我会再次提出问题,但有更多细节。

我已经实施了基于this tutorial的基于HMAC的安全性。

我有一个可以创建正确标头的C#应用​​程序(我故意设置静态时间戳和nonce - 仅用于测试):

private string CreateHeader(string url)
{
    string appId = "test";
    string apiKey = "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc=";

    string requestTimeStamp = "1521622403";
    string nonce = "715de35a4bfd4912baaa16daef21992d";

    url = Uri.EscapeUriString(url.ToLower());

    string signatureRawData = String.Format("{0}{1}{2}{3}", appId, url, requestTimeStamp, nonce);

    byte[]secretKeyByteArray = Convert.FromBase64String(apiKey);
    byte[] signature = Encoding.UTF8.GetBytes(signatureRawData);

    using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray))
    {
        byte[] signatureBytes = hmac.ComputeHash(signature);
        string requestSignatureBase64String = Convert.ToBase64String(signatureBytes);
        return string.Format("{0}:{1}:{2}:{3}", appId, requestSignatureBase64String, nonce, requestTimeStamp);
    }
}

这会计算此标头:test:fhqxcZll+3ZRQi3vRexbNyoT00Yqdoyq3CrAdGQ+4kE=:715de35a4bfd4912baaa16daef21992d:1521622403

不是我试图创建将生成相同标头的Postman预请求脚本。这是我的剧本:

function getAuthHeader(httpMethod, requestUrl, requestBody) {
    var CLIENT_KEY = 'test';
    var SECRET_KEY = 'A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc=';

    var requestTimeStamp = "1521622403";
    var nonce  = "715de35a4bfd4912baaa16daef21992d"
    requestUrl = requestUrl.toLowerCase();

    var signatureRawData = CLIENT_KEY+requestUrl+requestTimeStamp+nonce;
    console.log("signatureRawData: "+signatureRawData);

    var x = CryptoJS.enc.Utf8.parse(SECRET_KEY);

    var hash = CryptoJS.HmacSHA256(signatureRawData, x);
    var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);

    var header = [CLIENT_KEY, hashInBase64, nonce, requestTimeStamp].join(":");
    console.log("header: "+ header);

    return header;
}

postman.setEnvironmentVariable('hmacAuthHeader', getAuthHeader(request['method'], request['url'], request['data']));

但我得到不同的标头值: test:2ITrhVxr1/4BOxNVNcECnaSh0cW36LiMZWVQ0DaFncY=:715de35a4bfd4912baaa16daef21992d:1521622403

在C#中我将密钥和数据转换为散列到byte[],这可能就是问题所在。我怎样才能在JavaScript中做同样的事情?
C#需要byte[]作为[{1}}和HMACSHA256中的参数。

我正在寻找一种从C#和JavaScript(Postman预请求脚本)生成相同HMACSHA256的方法

1 个答案:

答案 0 :(得分:0)

在JS中纠正散列的解决方案是关键。在C#中我打电话:

function S4() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1); 
}

function GetNonce() {
    return (S4() + S4() + S4()+ S4() + S4() + S4() + S4()+ S4()).toLowerCase();
}

function GetTimeStamp() {
    var d = new Date();
    return Math.round(d.getTime() / 1000);
}

function getAuthHeader(httpMethod, requestUrl, requestBody) {
    var CLIENT_KEY = postman.getEnvironmentVariable('api_user');
    var SECRET_KEY = postman.getEnvironmentVariable('api_key');
    var AUTH_TYPE = 'HMAC';

    var requestTimeStamp = GetTimeStamp();
    var nonce = GetNonce();
    requestUrl = requestUrl.toLowerCase();

    var signatureRawData = [CLIENT_KEY,requestUrl,requestTimeStamp,nonce].join("");
    var key = CryptoJS.enc.Base64.parse(SECRET_KEY);

    var hash = CryptoJS.HmacSHA256(signatureRawData, key);
    var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);

    var header = [CLIENT_KEY, hashInBase64, nonce, requestTimeStamp].join(":");
    console.log("header: "+ header);

    return AUTH_TYPE+" "+header;
}

postman.setEnvironmentVariable('hmacAuthHeader', getAuthHeader(request['method'], request['url'], request['data']));

在我使用该密钥之前,在JS中我传递了原始的base64编码值。

以下是更正前请求脚本:

loc

在我寻找解决方案的过程中,我找到了很多语言的hmac sha256实现清单:https://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/

相关问题