MD5
Encode a string using an MD5 algorithm. The algorithm can be found on wikipedia.
You are encouraged to solve this task according to the task description, using any language you may know.
Optionally, validate your implementation by running all of the test values in IETF RFC (1321) for MD5. Additional the RFC provides more precise information on the algorithm than the Wikipedia article.
If the solution on this page is a library solution, see MD5/Implementation for an implementation from scratch.
Ada
<lang ada>with Ada.Text_IO; use Ada.Text_IO; with GNAT.MD5;
procedure MD5_Digest is begin
Put(GNAT.MD5.Digest("Foo bar baz"));
end MD5_Digest;</lang>
AutoHotkey
Search autohotkey.com: [1]
Regular version
Source: AutoHotkey forum by SKAN <lang autohotkey>data := "abc" MsgBox % MD5(data,StrLen(data)) ; 900150983cd24fb0d6963f7d28e17f72
MD5( ByRef V, L=0 ) {
VarSetCapacity( MD5_CTX,104,0 ), DllCall( "advapi32\MD5Init", Str,MD5_CTX ) DllCall( "advapi32\MD5Update", Str,MD5_CTX, Str,V, UInt,L ? L : VarSetCapacity(V) ) DllCall( "advapi32\MD5Final", Str,MD5_CTX ) Loop % StrLen( Hex:="123456789ABCDEF0" ) N := NumGet( MD5_CTX,87+A_Index,"Char"), MD5 .= SubStr(Hex,N>>4,1) . SubStr(Hex,N&15,1)
Return MD5 } }</lang>
Native implementation
Source: AutoHotkey forum by Laszlo <lang autohotkey>; GLOBAL CONSTANTS r[64], k[64] r = 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22 , 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20 , 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23 , 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 StringSplit r, r, `, r0 := 7 Loop 64
i := A_Index-1, k%i% := floor(abs(sin(A_Index)) * 2**32)
- TEST CASES
MsgBox % MD5(x:="", 0) ; d41d8cd98f00b204e9800998ecf8427e MsgBox % MD5(x:="a", StrLen(x)) ; 0cc175b9c0f1b6a831c399e269772661 MsgBox % MD5(x:="abc", StrLen(x)) ; 900150983cd24fb0d6963f7d28e17f72 MsgBox % MD5(x:="message digest", StrLen(x)) ; f96b697d7cb7938d525a2f31aaf161d0 MsgBox % MD5(x:="abcdefghijklmnopqrstuvwxyz", StrLen(x))
- c3fcd3d76192e4007dfb496cca67e13b
MsgBox % MD5(x:="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", StrLen(x))
- d174ab98d277d9f5a5611c2c9f419d9f
MsgBox % MD5(x:="12345678901234567890123456789012345678901234567890123456789012345678901234567890", StrLen(x))
- 57edf4a22be3c955ac49da2e2107b67a
MsgBox % MD5(x:="The quick brown fox jumps over the lazy dog", StrLen(x))
- 9e107d9d372bb6826bd81d3542a419d6
MsgBox % MD5(x:="The quick brown fox jumps over the lazy cog", StrLen(x))
- 1055d3e698d289f2af8663725127bd4b
MD5(ByRef Buf, L) { ; Binary buffer, Length in bytes
Static P, Q, N, i, a,b,c,d, t, h0,h1,h2,h3, y = 0xFFFFFFFF
h0 := 0x67452301, h1 := 0xEFCDAB89, h2 := 0x98BADCFE, h3 := 0x10325476
N := ceil((L+9)/64)*64 ; padded length (100..separator, 8B length) VarSetCapacity(Q,N,0) ; room for padded data P := &Q ; pointer DllCall("RtlMoveMemory", UInt,P, UInt,&Buf, UInt,L) ; copy data DllCall("RtlFillMemory", UInt,P+L, UInt,1, UInt,0x80) ; pad separator DllCall("ntdll.dll\RtlFillMemoryUlong",UInt,P+N-8,UInt,4,UInt,8*L) ; at end: length in bits < 512 MB
Loop % N//64 { Loop 16 i := A_Index-1, w%i% := *P | *(P+1)<<8 | *(P+2)<<16 | *(P+3)<<24, P += 4
a := h0, b := h1, c := h2, d := h3
Loop 64 { i := A_Index-1 If i < 16 f := (b & c) | (~b & d), g := i Else If i < 32 f := (d & b) | (~d & c), g := 5*i+1 & 15 Else If i < 48 f := b ^ c ^ d, g := 3*i+5 & 15 Else f := c ^ (b | ~d), g := 7*i & 15
t := d, d := c, c := b b += rotate(a + f + k%i% + w%g%, r%i%) ; reduced to 32 bits later a := t }
h0 := h0+a & y, h1 := h1+b & y, h2 := h2+c & y, h3 := h3+d & y } Return hex(h0) . hex(h1) . hex(h2) . hex(h3)
}
rotate(a,b) { ; 32-bit rotate a to left by b bits, bit32..63 garbage
Return a << b | (a & 0xFFFFFFFF) >> (32-b)
}
hex(x) { ; 32-bit little endian hex digits
SetFormat Integer, HEX x += 0x100000000, x := SubStr(x,-1) . SubStr(x,8,2) . SubStr(x,6,2) . SubStr(x,4,2) SetFormat Integer, DECIMAL Return x
}</lang>
BBC BASIC
See MD5/Implementation for a native version. <lang bbcbasic> PRINT FN_MD5("")
PRINT FN_MD5("a") PRINT FN_MD5("abc") PRINT FN_MD5("message digest") PRINT FN_MD5("abcdefghijklmnopqrstuvwxyz") PRINT FN_MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") PRINT FN_MD5(STRING$(8,"1234567890")) END DEF FN_MD5(message$) LOCAL I%, MD5$, MD5_CTX{} DIM MD5_CTX{i%(1), buf%(3), in&(63), digest&(15)} SYS "MD5Init", MD5_CTX{} SYS "MD5Update", MD5_CTX{}, message$, LEN(message$) SYS "MD5Final", MD5_CTX{} FOR I% = 0 TO 15 MD5$ += RIGHT$("0"+STR$~(MD5_CTX.digest&(I%)),2) NEXT = MD5$</lang>
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <openssl/md5.h>
const char *string = "The quick brown fox jumped over the lazy dog's back";
int main() {
int i; unsigned char result[MD5_DIGEST_LENGTH];
MD5(string, strlen(string), result);
// output for(i = 0; i < MD5_DIGEST_LENGTH; i++) printf("%02x", result[i]); printf("\n");
return EXIT_SUCCESS;
}</lang> Implementation of md5 <lang c>#include <stdlib.h>
- include <stdio.h>
- include <string.h>
- include <math.h>
typedef union uwb {
unsigned w; unsigned char b[4];
} WBunion;
typedef unsigned Digest[4];
unsigned f0( unsigned abcd[] ){
return ( abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]);}
unsigned f1( unsigned abcd[] ){
return ( abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]);}
unsigned f2( unsigned abcd[] ){
return abcd[1] ^ abcd[2] ^ abcd[3];}
unsigned f3( unsigned abcd[] ){
return abcd[2] ^ (abcd[1] |~ abcd[3]);}
typedef unsigned (*DgstFctn)(unsigned a[]);
unsigned *calcKs( unsigned *k) {
double s, pwr; int i;
pwr = pow( 2, 32); for (i=0; i<64; i++) { s = fabs(sin(1+i)); k[i] = (unsigned)( s * pwr ); } return k;
}
// ROtate v Left by amt bits unsigned rol( unsigned v, short amt ) {
unsigned msk1 = (1<<amt) -1; return ((v>>(32-amt)) & msk1) | ((v<<amt) & ~msk1);
}
unsigned *md5( const char *msg, int mlen) {
static Digest h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
// static Digest h0 = { 0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210 };
static DgstFctn ff[] = { &f0, &f1, &f2, &f3 }; static short M[] = { 1, 5, 3, 7 }; static short O[] = { 0, 1, 5, 0 }; static short rot0[] = { 7,12,17,22}; static short rot1[] = { 5, 9,14,20}; static short rot2[] = { 4,11,16,23}; static short rot3[] = { 6,10,15,21}; static short *rots[] = {rot0, rot1, rot2, rot3 }; static unsigned kspace[64]; static unsigned *k;
static Digest h; Digest abcd; DgstFctn fctn; short m, o, g; unsigned f; short *rotn; union { unsigned w[16]; char b[64]; }mm; int os = 0; int grp, grps, q, p; unsigned char *msg2;
if (k==NULL) k= calcKs(kspace);
for (q=0; q<4; q++) h[q] = h0[q]; // initialize
{ grps = 1 + (mlen+8)/64; msg2 = malloc( 64*grps); memcpy( msg2, msg, mlen); msg2[mlen] = (unsigned char)0x80; q = mlen + 1; while (q < 64*grps){ msg2[q] = 0; q++ ; } {
// unsigned char t;
WBunion u; u.w = 8*mlen;
// t = u.b[0]; u.b[0] = u.b[3]; u.b[3] = t; // t = u.b[1]; u.b[1] = u.b[2]; u.b[2] = t;
q -= 8; memcpy(msg2+q, &u.w, 4 ); } }
for (grp=0; grp<grps; grp++) { memcpy( mm.b, msg2+os, 64); for(q=0;q<4;q++) abcd[q] = h[q]; for (p = 0; p<4; p++) { fctn = ff[p]; rotn = rots[p]; m = M[p]; o= O[p]; for (q=0; q<16; q++) { g = (m*q + o) % 16; f = abcd[1] + rol( abcd[0]+ fctn(abcd) + k[q+16*p] + mm.w[g], rotn[q%4]);
abcd[0] = abcd[3]; abcd[3] = abcd[2]; abcd[2] = abcd[1]; abcd[1] = f; } } for (p=0; p<4; p++) h[p] += abcd[p]; os += 64; } return h;
}
int main( int argc, char *argv[] ) {
int j,k; const char *msg = "The quick brown fox jumps over the lazy dog."; unsigned *d = md5(msg, strlen(msg)); WBunion u;
printf("= 0x"); for (j=0;j<4; j++){ u.w = d[j]; for (k=0;k<4;k++) printf("%02x",u.b[k]); } printf("\n");
return 0;
}</lang>
C#
<lang csharp>using System.Text; using System.Security.Cryptography;
byte[] data = Encoding.ASCII.GetBytes("The quick brown fox jumped over the lazy dog's back"); byte[] hash = MD5.Create().ComputeHash(data); Console.WriteLine(BitConverter.ToString(hash).Replace("-", "").ToLower());</lang>
Clojure
<lang lisp>(apply str
(map (partial format "%02x") (.digest (doto (java.security.MessageDigest/getInstance "MD5") .reset (.update (.getBytes "The quick brown fox jumps over the lazy dog"))))))</lang>
Common Lisp
This one uses a library, but if you want to see how it's implemented, press M-x slime-edit-definition and go to md5:md5sum-stream. <lang lisp>(require #+sbcl 'sb-md5 #-sbcl 'md5)
(defun octets->letters (octet-vector)
(with-output-to-string (stream) (loop for i across octet-vector do (flet ((foo (x) (digit-char (ldb (byte x (- x 4)) i) 16))) (princ (foo 8) stream) (princ (foo 4) stream)))))
(defun md5 (string)
(octets->letters #+sbcl (sb-md5:md5sum-string string) #-sbcl (with-input-from-string (stream string) (md5:md5sum-stream stream))))</lang>
CL-USER> (md5 "foo") "acbd18db4cc2f85cedef654fccc4a4d8"
D
<lang d>import std.stdio, std.md5;
void main() {
ubyte[16] digest; auto txt = "The quick brown fox jumped over the lazy dog's back"; sum(digest, txt); writeln(digest.digestToString());
}</lang> Output:
E38CA1D920C4B8B8D3946B2C72F01680
Alternative version:
<lang d>import tango.io.digest.Md5, tango.io.Stdout;
void main(char[][] args) {
auto md5 = new Md5(); for(int i = 1; i < args.length; i++) { md5.update(args[i]); Stdout.formatln("[{}]=>\n[{}]", args[i], md5.hexDigest()); }
}</lang> Output:
>md5test "The quick brown fox jumped over the lazy dog's back" [The quick brown fox jumped over the lazy dog's back]=> [e38ca1d920c4b8b8d3946b2c72f01680]
Delphi
If you require a native implementation, look inside the class TIdHashMessageDigest5. This class is placed in the unit IdHashMessageDigest.pas. <lang Delphi>program MD5Hash;
{$APPTYPE CONSOLE}
uses
SysUtils, IdHashMessageDigest;
function MD5(aValue: string): string; begin
with TIdHashMessageDigest5.Create do begin Result:= HashStringAsHex(aValue); Free; end;
end;
begin
Writeln(MD5()); Writeln(MD5('a')); Writeln(MD5('abc')); Writeln(MD5('message digest')); Writeln(MD5('abcdefghijklmnopqrstuvwxyz')); Writeln(MD5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')); Writeln(MD5('12345678901234567890123456789012345678901234567890123456789012345678901234567890')); Readln;
end.</lang> Output:
D41D8CD98F00B204E9800998ECF8427E 0CC175B9C0F1B6A831C399E269772661 900150983CD24FB0D6963F7D28E17F72 F96B697D7CB7938D525A2F31AAF161D0 C3FCD3D76192E4007DFB496CCA67E13B D174AB98D277D9F5A5611C2C9F419D9F 57EDF4A22BE3C955AC49DA2E2107B67A
E
(with modifications)
<lang e>def makeMessageDigest := <import:java.security.makeMessageDigest> def sprintf := <import:java.lang.makeString>.format
def digest := makeMessageDigest.getInstance("MD5") \
.digest("The quick brown fox jumped over the lazy dog's back".getBytes("iso-8859-1"))
for b in digest {
print(sprintf("%02x", [b]))
} println()</lang>
Erlang
By default, Erlang's crypto functions like md5 return a binary value rather than a hex string. We have two write our own function to translate it: <lang Erlang>-module(tests). -export([md5/1]).
md5(S) ->
string:to_upper( lists:flatten([io_lib:format("~2.16.0b",[N]) || <<N>> <= erlang:md5(S)]) ).</lang>
Testing it: <lang erlang>1> c(tests). {ok,tests} 2> tests:md5("The quick brown fox jumped over the lazy dog's back"). "E38CA1D920C4B8B8D3946B2C72F01680"</lang>
Factor
Using builtin library:
USING: kernel strings io checksums checksums.md5 ; "The quick brown fox jumps over the lazy dog" md5 checksum-bytes hex-string print
Forth
<lang forth>include ffl/md5.fs
\ Create a MD5 variable md1 in the dictionary
md5-create md1
\ Update the variable with data
s" The quick brown fox jumps over the lazy dog" md1 md5-update
\ Finish the MD5 calculation resulting in four unsigned 32 bit words \ on the stack representing the hash value
md1 md5-finish
\ Convert the hash value to a hex string and print it
md5+to-string type cr</lang>
Frink
The messageDigest[string, hash]
returns a hex-encoded hash of any input string with a variety of hashing functions.
<lang frink>println[messageDigest["The quick brown fox", "MD5"]]</lang>
Go
<lang go>package main
import (
"crypto/md5" "fmt"
)
func main() {
for _, p := range [][2]string{ // RFC 1321 test cases {"d41d8cd98f00b204e9800998ecf8427e", ""}, {"0cc175b9c0f1b6a831c399e269772661", "a"}, {"900150983cd24fb0d6963f7d28e17f72", "abc"}, {"f96b697d7cb7938d525a2f31aaf161d0", "message digest"}, {"c3fcd3d76192e4007dfb496cca67e13b", "abcdefghijklmnopqrstuvwxyz"}, {"d174ab98d277d9f5a5611c2c9f419d9f", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, {"57edf4a22be3c955ac49da2e2107b67a", "12345678901234567890" + "123456789012345678901234567890123456789012345678901234567890"}, // test case popular with other RC solutions {"e38ca1d920c4b8b8d3946b2c72f01680", "The quick brown fox jumped over the lazy dog's back"}, } { validate(p[0], p[1]) }
}
var h = md5.New()
func validate(check, s string) {
h.Reset() h.Write([]byte(s)) sum := fmt.Sprintf("%x", h.Sum(nil)) if sum != check { fmt.Println("MD5 fail") fmt.Println(" for string,", s) fmt.Println(" expected: ", check) fmt.Println(" got: ", sum) }
}</lang>
Haskell
Use modules nano-MD5 and ByteString from HackageDB <lang Haskell>import Data.Digest.OpenSSL.MD5(md5sum);import Data.ByteString(pack);import Data.Char(ord)
main = do
putStrLn $ md5sum $ pack $ map (fromIntegral.ord) "The quick brown fox jumped over the lazy dog's back"</lang>
Use in GHCi:
*Main> main e38ca1d920c4b8b8d3946b2c72f01680
Io
<lang io>Io> MD5 ==> MD5_0x97663e0:
appendSeq = MD5_appendSeq() md5 = MD5_md5() md5String = MD5_md5String()
Io> MD5 clone appendSeq("The quick brown fox jumped over the lazy dog's back") md5String ==> e38ca1d920c4b8b8d3946b2c72f01680</lang>
Icon and Unicon
The following program demonstrates the MD5 using a native Icon/Unicon implementation (see MD5/Implementation) and checks the results against reference values. Alternate implementations using call outs to md5sum on Linux or fciv on windows are possible but were not coded. <lang Icon>procedure main() # validate against the RFC test strings and more
testMD5("The quick brown fox jumps over the lazy dog", 16r9e107d9d372bb6826bd81d3542a419d6) testMD5("The quick brown fox jumps over the lazy dog.", 16re4d909c290d0fb1ca068ffaddf22cbd0) testMD5("", 16rd41d8cd98f00b204e9800998ecf8427e)
end
procedure testMD5(s,rh) # compute the MD5 hash and compare it to reference value
write("Message(length=",*s,") = ",image(s)) write("Digest = ",hexstring(h := MD5(s)),if h = rh then " matches reference hash" else (" does not match reference hash = " || hexstring(rh)),"\n")
end</lang>
Sample Output:
Message(length=43) = "The quick brown fox jumps over the lazy dog" Digest = 9E107D9D372BB6826BD81D3542A419D6 matches reference hash Message(length=44) = "The quick brown fox jumps over the lazy dog." Digest = E4D909C290D0FB1CA068FFADDF22CBD0 matches reference hash Message(length=0) = "" Digest = D41D8CD98F00B204E9800998ECF8427E matches reference hash
J
Using the md5 script from the convert/misc addon package: <lang j> require 'convert/misc/md5'
md5 'The quick brown fox jumped over the lazy dogs back'
e38ca1d920c4b8b8d3946b2c72f01680</lang>
Java
Modified from mindprod's Java Glossary: <lang java>import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
/**
* Test MD5 digest computation * * @author Roedy Green * @version 1.0 * @since 2004-06-07 */
public final class MD5{ public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException{ byte[] theTextToDigestAsBytes= "The quick brown fox jumped over the lazy dog's back" .getBytes("8859_1"); MessageDigest md= MessageDigest.getInstance("MD5"); md.update(theTextToDigestAsBytes); byte[] digest= md.digest();
// dump out the hash for(byte b: digest){ System.out.printf("%02X", b & 0xff); } System.out.println(); } }</lang> Other options for digest algorithms (to replace "MD5" in the example above) include: MD2, SHA-1, SHA-256, SHA-384, and SHA-512. Other encoding options (to replace "8859_1" in the example above) include: UTF-8, UTF-16, and ASCII.
Liberty BASIC
<lang lb>'[RC]MD5
'from tsh73's January 2008 code
text$="The quick brown fox jumps over the lazy dog" checkSum$="9e107d9d372bb6826bd81d3542a419d6"
print text$ print checkSum$
test$=md5$(text$)
if test$=checkSum$ then print "passed" print test$ else print "failed" end if end
function md5$(text$)
dim r(64) dim k(64) dim w(16) global two32 two32=2^32
'prepare the MD5 checksum table restore [perRoundShiftAmounts] for i=0 to 63 read x r(i)=x next
'prepare constants for i=0 to 63 k(i) = int(abs(sin(i+1)) * two32) next
'initialise variables h0 = HEXDEC("67452301") h1 = HEXDEC("EFCDAB89") h2 = HEXDEC("98BADCFE") h3 = HEXDEC("10325476")
'find num bits in message numbits=len(text$)*8
'add bits "10000000" text$=text$+chr$(128)
'add bits "00000000" while len(text$) mod 64 <> 56 text$=text$+chr$(0) wend
'add original length in bits text$=text$+dec2asc$(numbits)
'MD5 rounds 'process in 64 byte chunks 512bits for chunk = 1 to len(text$) step 64 chunk$ = mid$(text$, chunk, 64) for word = 0 TO 15 'invert byte order b0 = asc(mid$(chunk$, word*4+1, 1)) b1 = asc(mid$(chunk$, word*4+2, 1)) b2 = asc(mid$(chunk$, word*4+3, 1)) b3 = asc(mid$(chunk$, word*4+4, 1)) w(word) = ((b3*256+b2)*256+b1)*256+b0 next word a = h0 b = h1 c = h2 d = h3 for i = 0 to 63 select case case 0 <= i and i <= 15 f = (b and c) or (bitNot(b) and d) g = i case 16 <= i and i <= 31 f = (d and b) or (bitNot(d) and c) g = (5 * i + 1) mod 16 case 32 <= i and i <= 47 f = b xor c xor d g = (3 * i + 5) mod 16 case 48 <= i and i <= 63 f = c xor (b or bitNot(d)) g = (7 * i) mod 16 end select temp = d d = c c = b b=b+leftrotate(a + f + k(i) + w(g),r(i)) b = b mod two32 a = temp next i h0 = (h0 + a) mod two32 h1 = (h1 + b) mod two32 h2 = (h2 + c) mod two32 h3 = (h3 + d) mod two32 next chunk
md5$ = revOrd$(DECHEX$(h0))+_ revOrd$(DECHEX$(h1))+_ revOrd$(DECHEX$(h2))+_ revOrd$(DECHEX$(h3))
[perRoundShiftAmounts] DATA 7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22 DATA 5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20 DATA 4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23 DATA 6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
end function
' dec2asc: dec to 8 byte asc function dec2asc$(n) h$ = "" for i = 1 to 8 h$ = h$ + chr$(n mod 256) n = int(n/256) next dec2asc$= h$ end function
' bitNot function bitNot(num) bitNot = two32 -1 -num end function
' leftrotate: spins bits left n times function leftrotate(num,times) num=num mod two32 r = (num*2^times) mod two32 l = int(num/(2^(32-times))) leftrotate = r+l end function
' reverse the HEXDEC$ order function revOrd$(a$) a$=left$("00000000", 8-len(a$))+a$ revOrd$ = lower$(mid$(a$,7,2)+mid$(a$,5,2)+mid$(a$,3,2)+mid$(a$,1,2)) end function</lang>
Lua
Using the Kepler MD5 library: <lang Lua>require "md5"
--printing a sum: print(md5.sumhexa"The quick brown fox jumps over the lazy dog")
--running the test suite:
local function test(msg,sum) assert(md5.sumhexa(msg)==sum) end
test("","d41d8cd98f00b204e9800998ecf8427e") test("a","0cc175b9c0f1b6a831c399e269772661") test("abc","900150983cd24fb0d6963f7d28e17f72") test("message digest","f96b697d7cb7938d525a2f31aaf161d0") test("abcdefghijklmnopqrstuvwxyz","c3fcd3d76192e4007dfb496cca67e13b") test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789","d174ab98d277d9f5a5611c2c9f419d9f") test("12345678901234567890123456789012345678901234567890123456789012345678901234567890","57edf4a22be3c955ac49da2e2107b67a")</lang>
Mathematica
Mathematica has built-in function Hash and FileHash, it should be noted that Hash["hello","MD5"] would give the MD5 of ""hello"" in stead of "hello". This is done because it wants to distinguish between the variable hello and the string "hello". A workaround for getting MD5's from strings would be: <lang Mathematica> StringHash[string_String]:=Module[{stream=OpenWrite[],file,hash},
WriteString[stream,string]; file=Close[stream]; hash=FileHash[file,"MD5"]; DeleteFile[file]; hash ]</lang>
Example: <lang Mathematica> StringHash["The quick brown fox jumped over the lazy dog's back"] // BaseForm[#, 16] &</lang> gives back: <lang Mathematica> e38ca1d920c4b8b8d3946b2c72f01680</lang>
MATLAB
A fast implementation can be found here: MATLAB Central. The file to which I have linked uses MATLAB's Java language interface to use the MD5 algorithm built into Java's compiler libraries.
A MATLAB implementation is below. It is an almost direct translation of the pseudo-code given in the MD5 wikipedia entry. Unfortunately, there is something wrong with this implementation. It does not return the correct hash of the input. I think it has something to do with the endianness of some of the variables. Despite that, this is a decent example of how this algorithm might be implemented. This implementation requires this file in order to run.
<lang MATLAB>function digest = md5(message)
%% Helper Function Definitions
%This function converts a binary representation of a number or vector %of numbers from a string to a row vector of 1's and 0's function matrix = binStr2mat(binStr) matrix = zeros(size(binStr)); for n = (1:numel(binStr)) matrix(n) = str2double(binStr(n)); end end
%This acts as a "lower <= x <= upper" operator function trueFalse = inRange(lowerBound,theValue,upperBound) trueFalse = (lowerBound <= theValue) && (theValue <= upperBound); end
%This converts a decimal number into its 32-bit binary representation, %and I'm pretty sure it is little-endian function binaryRep = to32BitBin(decimal) binaryRep = binStr2mat(dec2bin(decimal,32)); end
%This converts a decimal number into its 64-bit binary representation, %and I'm pretty sure it is little-endian function binaryRep = to64BitBin(decimal) binaryRep = binStr2mat(dec2bin(decimal,64)); end
%This adds multiple binary numbers together modulo 2^32. The sum of these %numbers will rap around if the sum of two numbers is >= 2^32 function result = addBinary(varargin) result = 0; for l = (1:numel(varargin)) temp = num2str(varargin{l}); temp(temp == ' ') = []; result = mod(result + bin2dec(temp),2^32); end result = to32BitBin(result); end
%% MD5 Hash Algorithm
%Define constants
%r is the bit-shift amount for each round r =[7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,... 9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,... 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21]; %Use the binary representation of the radian values of sine represented %as 32-bit integers k = to32BitBin(floor(abs(sin(1:64)).*(2^32)));
%Initialize the hash variables, convert the hex representation of these
%variables to their 32-bit binary representation h0 = to32BitBin(hex2dec('67452301')); h1 = to32BitBin(hex2dec('EFCDAB89'));
h2 = to32BitBin(hex2dec('98BADCFE')); h3 = to32BitBin(hex2dec('10325476'));
%Convert the ASCII values of the input string to a binary string matrix message = dec2bin(message); N = numel(message); %Convert the message matrix to one long bit stream message = reshape(transpose(message),1,N); %Perform the pre-prossesing of appending a 1-bit to the message, then %enough zeros to make the length of the message congruent to 448 mod %512. Then append the 64-bit representation of the length of the %original message string to the end. message = [binStr2mat([message '1']) zeros(1,abs(mod(N+1,512) - 448)) to64BitBin(N)];
%Process 512-bit chunks of the pre-processed message string
for chunk = (1:(numel(message)/512)) %Stored the index of the first bit in the chunk blockIndex = ((chunk-1)*512)+1; %Pull out the 512-bit chunk from the message, then reshape it into %32, 16-bit strings. Then transpose that string matrix to recover 16, %32-bit words in the correct order. If we do this directly, by %reshaping the 512-bit chunk to 16, 32-bit strings the original %order of the bits will be scrambled. w = transpose(reshape(message(blockIndex:blockIndex+511),32,16)); %Initialize the hashes for this round a = h0; b = h1; c = h2; d = h3; %Process the hahes %Note: The original MD5 algorithm pseudo-code was written for %0-based arrays. Therefore, the calculation for "g" has been %modified for MATLAB's 1-based arrays for i = (1:64) if inRange(1,i,16) f = (b & c) | ((~b) & d); g = i; elseif inRange(17,i,32) f = (d & b) | ((~d) & c); g = mod( (5*(i-1)) + 1 ,16) + 1; elseif inRange(33,i,48) f = xor( b,xor(c,d) ); g = mod( (3*(i-1)) + 5 ,16) + 1; elseif inRange(48,i,64) f = xor( c, (b | (~d)) ); g = mod( (7*(i-1)),16 ) + 1; end temp = d; d = c; c = b; %The circshift has a -r(i) because normally this function %rotates right, not left. b = addBinary(b,circshift( addBinary(a,f,k(i,1:32),w(g,1:32)),[0 -r(i)] )); a = temp; end %Add this chunk's hash to all the previous chunks' hashes h0 = addBinary(h0,a); h1 = addBinary(h1,b); h2 = addBinary(h2,c); h3 = addBinary(h3,d); end %Concatenate the hashes together and convert them to a binary string digest = num2str([h0 h1 h2 h3]); %Remove whitespace from the digest, leaving 1's and 0's digest(digest == ' ') = []; %Convert the binary representation of the digest to a hexadecimal digest = lower(bin2hex(digest));
end %md5</lang> Sample Usage: <lang MATLAB>>> md5('The quick brown fox jumps over the lazy dog.')
ans =
c8cc939f167a20b55ddfe18c1b7f23f7 %This is not the correct hash</lang>
MOO
<lang moo>string = "The quick brown fox jumped over the lazy dog's back"; player:tell(string_hash(string));</lang>
Nemerle
<lang Nemerle>using System; using System.Console; using System.Text; using System.Security.Cryptography; using Nemerle.Collections; using Nemerle.Collections.NCollectionsExtensions;
module Md5 {
HashMD5(input : string) : string { BitConverter.ToString (MD5.Create().ComputeHash(Encoding.Default.GetBytes(input))).Replace("-", "").ToLower() } IsValidMD5(text : string, hash : string) : bool { HashMD5(text) == hash.ToLower() } Main() : void { def examples = ["The quick brown fox jumped over the lazy dog's back", "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"]; def hashes = ["e38ca1d920c4b8b8d3946b2c72f01680", "d41d8cd98f00b204e9800998ecf8427e", "0cc175b9c0f1b6a831c399e269772661", "900150983cd24fb0d6963f7d28e17f72", "f96b697d7cb7938d525a2f31aaf161d0", "c3fcd3d76192e4007dfb496cca67e13b", "d174ab98d277d9f5a5611c2c9f419d9f", "57edf4a22be3c955ac49da2e2107b67a"]; def tests = Hashtable(ZipLazy(examples, hashes)); foreach (test in tests) Write($"$(IsValidMD5(test.Key, test.Value)) "); }
}</lang> Output:
True True True True True True True True
NetRexx
<lang NetRexx>/* NetRexx */
options replace format comments java crossref savelog symbols binary
import java.security.MessageDigest
MD5('The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6') -- RFC 1321 MD5 test suite: MD5("", 'd41d8cd98f00b204e9800998ecf8427e') MD5("a", '0cc175b9c0f1b6a831c399e269772661') MD5("abc", '900150983cd24fb0d6963f7d28e17f72') MD5("message digest", 'f96b697d7cb7938d525a2f31aaf161d0') MD5("abcdefghijklmnopqrstuvwxyz", 'c3fcd3d76192e4007dfb496cca67e13b') MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 'd174ab98d277d9f5a5611c2c9f419d9f') MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", '57edf4a22be3c955ac49da2e2107b67a')
return
method MD5(messageText, verifyCheck) public static
message = String(messageText) messageBytes = byte[] digestBytes = byte[]
do messageBytes = message.getBytes('UTF-8') md = MessageDigest.getInstance('MD5') md.update(messageBytes) digestBytes = md.digest
digestSum = loop b_ = 0 to digestBytes.length - 1 bb = Rexx(digestBytes[b_]).d2x(2) digestSum = digestSum || bb.lower end b_
say '<Message>'message'</Message>' say ' <MD5>'digestSum'</MD5>' say ' <Verify>'verifyCheck'</Verify>' if digestSum == verifyCheck then say 'MD5 Confirmed' else say 'MD5 Failed' catch ex = Exception ex.printStackTrace end
return</lang>
Output:
<Message>The quick brown fox jumps over the lazy dog</Message> <MD5>9e107d9d372bb6826bd81d3542a419d6</MD5> <Verify>9e107d9d372bb6826bd81d3542a419d6</Verify> MD5 Confirmed <Message></Message> <MD5>d41d8cd98f00b204e9800998ecf8427e</MD5> <Verify>d41d8cd98f00b204e9800998ecf8427e</Verify> MD5 Confirmed <Message>a</Message> <MD5>0cc175b9c0f1b6a831c399e269772661</MD5> <Verify>0cc175b9c0f1b6a831c399e269772661</Verify> MD5 Confirmed <Message>abc</Message> <MD5>900150983cd24fb0d6963f7d28e17f72</MD5> <Verify>900150983cd24fb0d6963f7d28e17f72</Verify> MD5 Confirmed <Message>message digest</Message> <MD5>f96b697d7cb7938d525a2f31aaf161d0</MD5> <Verify>f96b697d7cb7938d525a2f31aaf161d0</Verify> MD5 Confirmed <Message>abcdefghijklmnopqrstuvwxyz</Message> <MD5>c3fcd3d76192e4007dfb496cca67e13b</MD5> <Verify>c3fcd3d76192e4007dfb496cca67e13b</Verify> MD5 Confirmed <Message>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789</Message> <MD5>d174ab98d277d9f5a5611c2c9f419d9f</MD5> <Verify>d174ab98d277d9f5a5611c2c9f419d9f</Verify> MD5 Confirmed <Message>12345678901234567890123456789012345678901234567890123456789012345678901234567890</Message> <MD5>57edf4a22be3c955ac49da2e2107b67a</MD5> <Verify>57edf4a22be3c955ac49da2e2107b67a</Verify> MD5 Confirmed
Objective-C
only; not Cocoa
<lang objc>NSString *myString = @"The quick brown fox jumped over the lazy dog's back"; NSData *digest = [[myString dataUsingEncoding:NSUTF8StringEncoding] md5Digest]; // or another encoding of your choosing NSLog(@"%@", [digest hexadecimalRepresentation]);</lang>
<lang objc>#import <CommonCrypto/CommonDigest.h>
NSString *myString = @"The quick brown fox jumped over the lazy dog's back"; NSData *data = [myString dataUsingEncoding:NSUTF8StringEncoding]; // or another encoding of your choosing unsigned char digest[CC_MD5_DIGEST_LENGTH]; if (CC_MD5([data bytes], [data length], digest)) {
NSMutableString *hex = [NSMutableString string]; for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { [hex appendFormat: @"%02x", (int)(digest[i])]; } NSLog(@"%@", hex);
}</lang>
(need to include "libcrypto.dylib" framework)
<lang objc>#include <openssl/md5.h>
NSString *myString = @"The quick brown fox jumped over the lazy dog's back"; NSData *data = [myString dataUsingEncoding:NSUTF8StringEncoding]; // or another encoding of your choosing unsigned char digest[MD5_DIGEST_LENGTH]; if (MD5([data bytes], [data length], digest)) {
NSMutableString *hex = [NSMutableString string]; for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { [hex appendFormat: @"%02x", (int)(digest[i])]; } NSLog(@"%@", hex);
}</lang>
OCaml
<lang ocaml># Digest.to_hex(Digest.string "The quick brown fox jumped over the lazy dog's back") ;; - : string = "e38ca1d920c4b8b8d3946b2c72f01680"</lang>
Octave
<lang octave>s = "The quick brown fox jumped over the lazy dog's back"; hash = md5sum(s, true); disp(hash)</lang>
OpenEdge/Progres
The MD5-DIGEST function is readily available, the output is passed thru HEX-ENCODE to convert the raw result to a hexadecimal string, this then needs to be passed thru STRING for display purposes. <lang progress>MESSAGE
1 STRING( HEX-ENCODE( MD5-DIGEST( "" ) ) ) SKIP 2 STRING( HEX-ENCODE( MD5-DIGEST( "a" ) ) ) SKIP 3 STRING( HEX-ENCODE( MD5-DIGEST( "abc" ) ) ) SKIP 4 STRING( HEX-ENCODE( MD5-DIGEST( "message digest" ) ) ) SKIP 5 STRING( HEX-ENCODE( MD5-DIGEST( "abcdefghijklmnopqrstuvwxyz" ) ) ) SKIP 6 STRING( HEX-ENCODE( MD5-DIGEST( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ) ) ) SKIP 7 STRING( HEX-ENCODE( MD5-DIGEST( "12345678901234567890123456789012345678901234567890123456789012345678901234567890" ) ) )
VIEW-AS ALERT-BOX</lang>
Output:
--------------------------- Message --------------------------- 1 d41d8cd98f00b204e9800998ecf8427e 2 0cc175b9c0f1b6a831c399e269772661 3 900150983cd24fb0d6963f7d28e17f72 4 f96b697d7cb7938d525a2f31aaf161d0 5 c3fcd3d76192e4007dfb496cca67e13b 6 d174ab98d277d9f5a5611c2c9f419d9f 7 57edf4a22be3c955ac49da2e2107b67a --------------------------- OK ---------------------------
Perl
<lang perl>use Digest::MD5 qw(md5_hex);
print md5_hex("The quick brown fox jumped over the lazy dog's back"), "\n";</lang>
The same in OO manner <lang perl>use Digest::MD5;
$md5 = Digest::MD5->new; $md5->add("The quick brown fox jumped over the lazy dog's back"); print $md5->hexdigest, "\n";</lang>
Perl 6
Library Digest::MD5 <lang perl6>use Digest::MD5; say Digest::MD5.md5_hex: "The quick brown fox jumped over the lazy dog's back";</lang>
PHP
<lang php>$string = "The quick brown fox jumped over the lazy dog's back"; echo md5( $string );</lang>
PicoLisp
Using the openssl library (the 'native' function is only in the 64-bit version available): <lang PicoLisp>(let Str "The quick brown fox jumped over the lazy dog's back"
(pack (mapcar hex (native "libcrypto.so" "MD5" '(B . 16) Str (length Str) '(NIL (16))) ) ) )</lang>
Output:
-> "E38CA1D920C4B8B8D3946B2C72F01680"
Pike
<lang pike>import String; import Crypto.MD5;
int main(){
write( string2hex( hash( "The quick brown fox jumped over the lazy dog's back" ) ) + "\n" );
}</lang>
PowerShell
<lang powershell>$string = "The quick brown fox jumped over the lazy dog's back" $data = [Text.Encoding]::UTF8.GetBytes($string) $hash = [Security.Cryptography.MD5]::Create().ComputeHash($data) ([BitConverter]::ToString($hash) -replace '-').ToLower()</lang>
PureBasic
<lang purebasic>test$ = "The quick brown fox jumped over the lazy dog's back" Debug MD5Fingerprint(@test$, StringByteLength(test$))</lang>
Python
Using builtin libraries:
- Python 3.x, 2.5 and later 2.x versions
<lang python>>>> import hashlib >>> # RFC 1321 test suite: >>> tests = (
(b"", 'd41d8cd98f00b204e9800998ecf8427e'), (b"a", '0cc175b9c0f1b6a831c399e269772661'), (b"abc", '900150983cd24fb0d6963f7d28e17f72'), (b"message digest", 'f96b697d7cb7938d525a2f31aaf161d0'), (b"abcdefghijklmnopqrstuvwxyz", 'c3fcd3d76192e4007dfb496cca67e13b'), (b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 'd174ab98d277d9f5a5611c2c9f419d9f'), (b"12345678901234567890123456789012345678901234567890123456789012345678901234567890", '57edf4a22be3c955ac49da2e2107b67a') )
>>> for text, golden in tests: assert hashlib.md5(text).hexdigest() == golden
>>> </lang>
- Python 2.5 and later
<lang python>>>> import hashlib >>> print hashlib.md5("The quick brown fox jumped over the lazy dog's back").hexdigest() e38ca1d920c4b8b8d3946b2c72f01680</lang>
- Pre-2.5; removed in 3.x
<lang python>>>> import md5 >>> print md5.md5("The quick brown fox jumped over the lazy dog's back").hexdigest() e38ca1d920c4b8b8d3946b2c72f01680</lang>
R
<lang R>library(digest) hexdigest <- digest("The quick brown fox jumped over the lazy dog's back",
algo="md5", serialize=FALSE)</lang>
REBOL
<lang rebol>>> checksum/method "The quick brown fox jumped over the lazy dog" 'md5 == #{08A008A01D498C404B0C30852B39D3B8}</lang>
RLaB
RLaB has a built-in function hash,
which implements hash functions fn as "md2", "md5", "sha", "sha1", "dss", "dss1" and "ripemd160", for given string vector ss and new-line delimiter nl. The last is here so that a hash of a string vector calculated in RLaB is the same as the hash of the same string vector written to a file.
<lang RLaB>>> x = "The quick brown fox jumped over the lazy dog's back" The quick brown fox jumped over the lazy dog's back
>> hash("md5", x) e38ca1d920c4b8b8d3946b2c72f01680</lang>
Ruby
<lang ruby>require 'digest/md5' Digest::MD5.hexdigest("The quick brown fox jumped over the lazy dog's back")
- => "e38ca1d920c4b8b8d3946b2c72f01680"</lang>
Slate
You must load the code in 'src/lib/md5.slate'. <lang slate>'The quick brown fox jumped over the lazy dog\'s back' md5String. "==> 'e38ca1d920c4b8b8d3946b2c72f01680'"</lang>
Smalltalk
<lang smalltalk>PackageLoader fileInPackage: 'Digest' ! (MD5 hexDigestOf: 'The quick brown fox jumped over the lazy dogs back') displayNl.</lang>
SQL
<lang sql>SELECT MD5('The quick brown fox jumped over the lazy dog\'s back')</lang>
Suneido
<lang Suneido>Md5('The quick brown fox jumped over the lazy dog\'s back')</lang>
Tcl
<lang tcl>package require md5 puts [md5::md5 -hex "The quick brown fox jumped over the lazy dog's back"]
- ==> E38CA1D920C4B8B8D3946B2C72F01680</lang>
UNIX Shell
UNIX Shells are typically scripting languages, so they execute system commands. (Such as md5sum, in this case.) The parameter "-n" has to be used, so no trailing newline is appended, which would change the MD5-hash.
<lang bash>echo -n "The quick brown fox jumped over the lazy dog's back" | md5sum</lang>