Search code examples
javascripterlangmnesiayaws

Erlang and JavaScript MD5 Digest match


Testing the Javascript Implementation of MD5 here: http://www.webtoolkit.info/javascript-md5.html gives the following output:

MD5("muzaaya") = "00e081abefbbbf72b2d5258196a9b6d0"

Going to my erlang shell, and calculating the MD5 of the same value i get this:

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 the two? If the MD5 result from the JavaScript front end app comes to my Erlang backend, i would like to be able to compare the two Digests. How can i match the Javascript MD5 digest to that of Erlang?


Solution

  • An MD5 hash is in essence a 128-bit number.

    You receive the MD5 value in Erlang as a binary of 16 bytes (16 * 8 = 128 bits). Each byte in that binary has to be converted into hexadecimal representation to be comparable to JavaScript's 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 and use the io_lib module to format it to a hexadecimal string. Then we use the flatten function to display it as a readable string (although this isn't necessary if you're going to write the value to a file or a socket since they are able to handle deep io lists, nested lists of characters or binaries).

    The format string used, ~2.16.0b means format an integer (b) using base 16 and padding to width 2 with the padding character 0 (see io:format/3 for a full guide).

    If you want a binary, you could use the following binary comprehension 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 it is faster)