在此处测试MD5的Javascript实施: http://www.webtoolkit.info/javascript-md5.html 提供以下输出:
MD5("muzaaya") = "00e081abefbbbf72b2d5258196a9b6d0"
转到我的erlang shell,并计算相同值的MD5,我得到了这个:
Eshell V5.8.4 (abort with ^G) 1> erlang:md5("muzaaya"). <<0,224,129,171,239,187,191,114,178,213,37,129,150,169, 182,208>> 2>
我如何比较两者?如果来自JavaScript前端应用程序的MD5结果来到我的Erlang后端,我希望能够比较两个摘要。如何将Javascript MD5摘要与Erlang的摘要相匹配?
答案 0 :(得分:16)
MD5哈希本质上是一个128位的数字。
您在Erlang中收到的MD5值为16字节的二进制(16 * 8 = 128位)。该二进制文件中的每个字节都必须转换为十六进制表示,以与JavaScript的MD5输出(每个字节有两个字符的十六进制字符串)相媲美:
2> lists:flatten([io_lib:format("~2.16.0b", [B]) || <<B>> <= MD5]).
"00e081abefbbbf72b2d5258196a9b6d0"
首先,我们从二进制文件中获取每个字节,然后使用io_lib
模块将其格式化为十六进制字符串。然后我们使用flatten函数将其显示为可读字符串(尽管如果您要将值写入文件或套接字,这是不必要的,因为它们能够处理深度io列表,嵌套字符列表或二进制文件)。
使用的格式字符串~2.16.0b
表示使用基本b
格式化整数(16
)并使用填充字符2
填充宽度0
(有关完整指南,请参阅io:format/3
。
如果你想要一个二进制文件,你可以使用以下二进制理解:
3> << << (list_to_binary(io_lib:format("~2.16.0b", [C])))/binary >>
|| <<C>> <= MD5 >>.
<<"00e081abefbbbf72b2d5258196a9b6d0">>
(而不是io_lib:format/2
还有http_util:integer_to_hexlist/1
,虽然我不知道它是否更快)
答案 1 :(得分:4)
又一个更快的版本:
hstr(B) when is_binary(B) ->
<< <<(hex(A)), (hex(B))>> || <<A:4,B:4>> <= B >>.
-compile({inline, [hex/1]}).
hex(0) -> $0;
hex(1) -> $1;
hex(2) -> $2;
hex(3) -> $3;
hex(4) -> $4;
hex(5) -> $5;
hex(6) -> $6;
hex(7) -> $7;
hex(8) -> $8;
hex(9) -> $9;
hex(10) -> $a;
hex(11) -> $b;
hex(12) -> $c;
hex(13) -> $d;
hex(14) -> $e;
hex(15) -> $f.
但最快的版本将是
md5_hex(L) ->
<< A1:4, A2:4, A3:4, A4:4, A5:4, A6:4, A7:4, A8:4,
A9:4, A10:4, A11:4, A12:4, A13:4, A14:4, A15:4, A16:4,
A17:4, A18:4, A19:4, A20:4, A21:4, A22:4, A23:4, A24:4,
A25:4, A26:4, A27:4, A28:4, A29:4, A30:4, A31:4, A32:4
>> = erlang:md5(L),
<< (hex(A1)), (hex(A2)), (hex(A3)), (hex(A4)),
(hex(A5)), (hex(A6)), (hex(A7)), (hex(A8)),
(hex(A9)), (hex(A10)), (hex(A11)), (hex(A12)),
(hex(A13)), (hex(A14)), (hex(A15)), (hex(A16)),
(hex(A17)), (hex(A18)), (hex(A19)), (hex(A20)),
(hex(A21)), (hex(A22)), (hex(A23)), (hex(A24)),
(hex(A25)), (hex(A26)), (hex(A27)), (hex(A28)),
(hex(A29)), (hex(A30)), (hex(A31)), (hex(A32)) >>.
但你不应该做这个优化。
编辑:此版本的hex/1
更快:
hex(X) ->
element(X+1, {$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $a, $b, $c, $d, $e, $f}).
EDIT2:另一种方法:
md5_hex(L) ->
<<X:128>> = erlang:md5(L),
B = integer_to_binary(X,16),
list_to_binary([lists:duplicate(32-byte_size(B),$0)|B]).
答案 2 :(得分:3)
如果你需要一个单行,它可以是这样的:
1> B = erlang:md5("muzaaya").
<<0,224,129,171,239,187,191,114,178,213,37,129,150,169,
182,208>>
2> lists:flatten([io_lib:format("~2.16.0b", [C]) || <<C>> <= B]).
"00e081abefbbbf72b2d5258196a9b6d0"
答案 3 :(得分:3)
这是位串理解版本,可能是速度最快,内存效率最高的:
hstr(B) when is_binary(B) ->
T = {$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$a,$b,$c,$d,$e,$f},
<< <<(element(X bsr 4 + 1, T)), (element(X band 16#0F + 1, T))>>
|| <<X:8>> <= B >>.
3&GT; L:hstr(二郎:MD5( “muzaaya”))。
4&GT; &LT;&LT; “00e081abefbbbf72b2d5258196a9b6d0” &GT;&GT;
答案 4 :(得分:2)
如果你想在JavaScript方面这样做,你可以使用这个
function md5HexToArray ( hexStr ) {
var i, arr = [], arraylength = hexStr.length/2;
for( i = 0; i < arraylength ; i++ ) {
arr[i] = parseInt( hexStr.substr(i*2,2), 16) ;
}
return arr;
};
但@Wrikken的评论看起来应该也可以正常工作。