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

HMAC-C#和JavaScript给出了不同的结果,javascript,c#,security,hmac,Javascript,C#,Security,Hmac,我的问题类似于,但因为问题缺少一些细节,答案也不是很有用,所以我再次提问,但有更多细节 我已经实现了基于HMAC的安全性,它基于 我有一个可以正常工作的C#应用程序,可以创建正确的头文件(我特意设置了静态时间戳和nonce,只是为了测试): 这将计算此标头:test:fhqxcZll+3ZRQi3vRexbNyoT00Yqdoyq3CrAdGQ+4kE=:715de35a4bfd4912baa16daef21992d:1521622403 不是,我正在尝试创建Postman预请求脚本,该脚本将生

我的问题类似于,但因为问题缺少一些细节,答案也不是很有用,所以我再次提问,但有更多细节

我已经实现了基于HMAC的安全性,它基于

我有一个可以正常工作的C#应用程序,可以创建正确的头文件(我特意设置了静态时间戳和nonce,只是为了测试):

这将计算此标头:
test:fhqxcZll+3ZRQi3vRexbNyoT00Yqdoyq3CrAdGQ+4kE=:715de35a4bfd4912baa16daef21992d: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/4boxnvncecnash0c36limzwvq0davency=:715de35a4bfd4912baa16daef21992d:1521622403

在C#中,我正在将密钥和数据转换为散列到
字节[]
,这可能就是问题所在。如何在JavaScript中执行相同的操作?
C#需要
byte[]
作为
HMACSHA256
ComputeHash
中的参数


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

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

byte[]secretKeyByteArray = Convert.FromBase64String(apiKey);
在使用该键之前,我在JS中传递原始的base64编码值

以下是更正的请求前脚本:

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']));

当我搜索解决方案时,我发现了很多语言的hmac sha256实现列表:

以及获得给定输出的目标
url
是什么?在javascript中,您也可以执行
CryptoJS.enc.Utf8.parse(SECRET\u KEY)
,它假定密钥是UTF-8字符串(实际上不是),而在C中,您可以正确地转换.FromBase64String(apiKey)。在C#中,出于某种原因,您也会执行
Uri.EscapeUriString
,但在javascript中,您不会这样做(通过
encodeURI
或类似方式)。@Evk很抱歉没有指定该参数-
http://localhost:63564/test/secure
@Evk我想我有办法了。在C#中,我在键上使用
FromBase64String
,但在JavaScript中没有这样做。添加
CryptoJS.enc.Base64.parse(秘钥)似乎解决了这个问题。我会检查tjat并发布答案,如果它有效的话。这不是我在上面的评论中说的吗?:)
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']));