我试图在Javascript中获取以下generate_hash erlang函数返回的相同值
-define(b2l(V), binary_to_list(V)).
-define(l2b(V), list_to_binary(V)).
generate_hash(User, Secret, TimeStamp) ->
SessionData = User ++ ":" ++ erlang:integer_to_list(TimeStamp, 16),
Hash = crypto:sha_mac(Secret, SessionData),
base64:encode(SessionData ++ ":" ++ ?b2l(Hash)).
make_time() ->
{NowMS, NowS, _} = erlang:now(),
NowMS * 1000000 + NowS.
以这种方式在erlang中调用此函数:
Username = "username"
Secret = ?l2b("secret"),
UserSalt = "usersalt",
CurrentTime = make_time(),
Hash = generate_hash( ?b2l(UserName), <<Secret/binary, UserSalt/binary>>, CurrentTime).
我设法使用google CryptoJS库计算哈希,但base64返回的值与erlang中返回的值不匹配。
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha1.js"></script>
function generate_hash(User, Secret, TimeStamp) {
var SessionData = User + ":" + parseInt(TimeStamp,16);
var hash = CryptoJS.HmacSHA1(Secret,SessionData);
return atob(SessionData + ":" + hash.toString())
}
var Hash = generate_hash( "username", "secret"+"usersalt", new Date().getTime())
alert(Hash);
答案 0 :(得分:2)
您的代码中存在三个问题。
首先:CryptoJS.HmacSHA1(Secret,SessionData);
的论点被颠倒了。它应该是CryptoJS.HmacSHA1(SessionData, Secret);
。
您可以在JS控制台中查看:
var hash = CryptoJS.HmacSHA1("b", "a");
0: 1717011798
1: -2038285946
2: -931908057
3: 823367506
4: 21804555
现在,转到Erlang控制台并输入:
crypto:sha_mac(<<"a">>, <<"b">>).
<<102,87,133,86,134,130,57,134,200,116,54,39,49,19,151,82,1,76,182,11>>
binary:encode_unsigned(1717011798).
<<102,87,133,86>>
binary:encode_unsigned(21804555).
<<1,76,182,11>>
我不知道有符号整数的等效方法,但事实证明,更改参数的顺序会给出相同的二进制值。
第二个问题是hash.toString()
,我的例子后面的内容是:
hash = CryptoJS.HmacSHA1("b", "a");
hash.toString();
"6657855686823986c874362731139752014cb60b"
而Erlang二进制列表将导致:
Str = binary_to_list(Hash).
[102,87,133,86,134,130,57,134,200,116,54,39,49,19,151,82,1,76,182,11]
io:format("~s", [Str]).
fWV9Èt6'1^SR^AL¶^K
我不确定toString对word数组的作用,但这会弄乱最终的结果。
第三个问题是,new Date().getTime()
将以毫秒为单位返回时间,而在Erlang中,则有微秒。但是,当您使用静态整数测试时,这应该无关紧要。
答案 1 :(得分:0)
两件事:
上面的Erlang代码中的make_time
函数返回自Unix纪元以来的秒的数量,而Javascript方法getTime
返回毫秒
除此之外,由于您可能没有在同一秒内运行这两个功能,因此您将获得不同的时间戳,因此无论如何都会有不同的哈希值。
Javascript函数parseInt
解析一个字符串并返回一个整数,而Erlang函数integer_to_list
取一个整数并将其转换为字符串(在Erlang中,字符串表示为列表,因此这个名字)。您可能希望改为使用toString
方法。
答案 2 :(得分:0)
该算法可以生成erlang
对应生成的相同字节序列:
var ret = [];
var hash = CryptoJS.HmacSHA1("b","a").words;
angular.forEach(hash,function(v){
var pos = v>=0, last=ret.length;
for(v=pos?v:v>>>0; v>0; v=Math.floor(v/256)) {
ret.splice(last, 0, v%256);
}
});
console.info(ret);
console.info(String.fromCharCode.apply(String,ret));
以上输出:
[102, 87, 133, 86, 134, 130, 57, 134, 200, 116, 54, 39, 49, 19, 151, 82, 1, 76, 182, 11]
fWV9Èt6'1RL¶