Erlang and JavaScript MD5 Digest match

Javascript Testing MD5 implementation here: http://www.webtoolkit.info/javascript-md5.html displays the following result:

  MD5 ("muzaaya") = "00e081abefbbbf72b2d5258196a9b6d0"

Going to my erlang shell and calculating MD5 of the same value, I get the following:

  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>

How can I compare these two? If MD5 comes to my Erlang server as a result of using the front end JavaScript application, I would like to compare the two digests. How can I map a Javascript MD5 digest to an Erlang array?

+5
source share
5 answers

The MD5 hash is essentially a 128-bit number.

You get the MD5 value in Erlang as a binary file of 16 bytes (16 * 8 = 128 bits). Each byte in this binary expression must be converted to a hexadecimal representation in order to be comparable to JavaScript MD5 output (which is a hexadecimal string with two characters per byte):

2> lists:flatten([io_lib:format("~2.16.0b", [B]) || <<B>> <= MD5]). "00e081abefbbbf72b2d5258196a9b6d0" 

First, we take each byte from the binary code and use the io_lib module to format it into a hexadecimal string. Then we use the flatten function to display it as a readable string (although this is not necessary if you intend to write the value to a file or socket, as they can handle deep io lists, nested character lists, or binary files).

The format string used is ~2.16.0b means integer ( b ) format using base 16 and indented to a width of 2 with a padding character of 0 (see io:format/3 for a complete guide).

If you want to use binary, you can use the following binary understanding instead:

 3> << << (list_to_binary(io_lib:format("~2.16.0b", [C])))/binary >> || <<C>> <= MD5 >>. <<"00e081abefbbbf72b2d5258196a9b6d0">> 

(Instead of io_lib:format/2 there is also http_util:integer_to_hexlist/1 , although I don't know if this is faster)

+16
source

Another and faster version:

 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. 

but the fastest version will be

 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)) >>. 

but you should not do this optimization.

EDIT: This hex/1 version is even faster:

 hex(X) -> element(X+1, {$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $a, $b, $c, $d, $e, $f}). 

EDIT2: another approach:

 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]). 
+4
source

If you need a single line, it could be something like this:

 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
source

Here's a bit string understanding version, arguably the fastest and most efficient memory:

 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> M: hstr (erlang: md5 ("muzaaya")).

4> <"00e081abefbbbf72b2d5258196a9b6d0" →

+3
source

If you want to do this on the JavaScript side, you can use this

 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; }; 

But @Wrikken's comment looks like it should work fine too.

+2
source

Source: https://habr.com/ru/post/893504/


All Articles