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