Thursday, February 09, 2006

MD5 in Erlang

Last week (20 Dec 2005) there is a question regarding how to do MD5 in Erlang in Erlang mailing list.

I replied by quoting the following resource :

In addition to what Bengt has said, you may want to
take a look at the following message thread. It
discussed how to generate MD5 hash like md5sum program :

http://www.erlang.org/ml-archive/erlang-questions/200303/msg00492.html
Jing sent me his code (modified from the above code) :
-module(hello).
-export([hex/1]).
-export([print_hash/0]).

hex(L) when list (L) ->
lists:flatten([hex(I) || I <- L]); hex(I) when I > 16#f ->
[hex0((I band 16#f0) bsr 4), hex0((I band 16#0f))];
hex(I) -> [$0, hex0(I)].

hex0(10) -> $a;
hex0(11) -> $b;
hex0(12) -> $c;
hex0(13) -> $d;
hex0(14) -> $e;
hex0(15) -> $f;
hex0(I) -> $0 +I.

print_hash()->
Hash = erlang:md5("hi"),
hexHash = hex(Hash),
ok = io:fwrite( "hi gives ~w~n", [ hexHash] ),
Hash.

Unfortunately, the code didn't work.

Two days ago I had a chance to take a look at the code. After look at the code, I finally figure out where the problems are :
  • [hex/1] function expect its argument in "list" type
  • [md5/1] function return binary type
to solve this problem I need to convert binary to list. Luckily there is a function binary_to_list()

Another problem I have spotted lies in io:fwrite() function, I need to set the output type to string :
ok = io:fwrite( "hi gives ~w~n", [ hexHash] ),
Without further ado, here is the improved-version code :
-module(test).
-export([hex/1]).
-export([print_hash/0]).

hex(L) when list (L) ->
lists:flatten([hex(I) || I <- L]); hex(I) when I > 16#f ->
[hex0((I band 16#f0) bsr 4), hex0((I band 16#0f))];
hex(I) -> [$0, hex0(I)].

hex0(10) -> $a;
hex0(11) -> $b;
hex0(12) -> $c;
hex0(13) -> $d;
hex0(14) -> $e;
hex0(15) -> $f;
hex0(I) -> $0 +I.

print_hash() ->
Hash = binary_to_list(erlang:md5("hello\n")),
HexHash = hex(Hash),
ok = io:fwrite("Hello gives ~s~n", [HexHash]).
I run the code in Erlang shell :
tedi@suse:~/projects/src/erlang> erl
Erlang (BEAM) emulator version 5.4.10 [source] [hipe]

Eshell V5.4.10 (abort with ^G)
1> c(test).
{ok,test}
2> test:print_hash().
Hello gives b1946ac92492d2347c6235b4d2611184
ok
3>

No comments: