Jump to content

MD5

From Rosetta Code
Task
MD5
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Encode a string using an MD5 algorithm.   The algorithm can be found on   Wikipedia.


Optionally, validate your implementation by running all of the test values in   IETF RFC (1321)   for MD5.

Additionally,   RFC 1321   provides more precise information on the algorithm than the Wikipedia article.

Warning:   MD5 has known weaknesses, including collisions and forged signatures.   Users may consider a stronger alternative when doing production-grade cryptography, such as SHA-256 (from the SHA-2 family), or the upcoming SHA-3.

If the solution on this page is a library solution, see   MD5/Implementation   for an implementation from scratch.

8th

"md5" cr:hash! "Some text" cr:hash cr:hash>s 
. cr bye
Output:

9db5682a4d778ca2cb79580bdb67083f

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
or android 64 bits with application Termux
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program MD5_64.s   */
 
/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
 
.equ MD5_DIGEST_LENGTH, 16
.equ ZWORKSIZE,        1000
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessRosetta:         .asciz "Rosetta Code"
szMessTest1:           .asciz "" 
szMessTest2:           .asciz "abc" 
szMessTest3:           .asciz "abcdefghijklmnopqrstuvwxyz"
szMessTest4:           .asciz "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
szMessTest5:           .asciz "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
szMessFinPgm:          .asciz "Program End ok.\n"
szMessResult:          .asciz "Result for "
szMessResult1:         .asciz " => "
szMessSizeError:       .asciz "\033[31mWork area too small !! \033[0m \n"
szCarriageReturn:      .asciz "\n"

/* array constantes K */
tbConstK:  .int 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee
           .int 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501
           .int 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be
           .int 0x6b901122,0xfd987193,0xa679438e,0x49b40821
           .int 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa
           .int 0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8
           .int 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed
           .int 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a
           .int 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c
           .int 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70
           .int 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05
           .int 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665
           .int 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039
           .int 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1
           .int 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1
           .int 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391  

/* array rotation coef R */
tbRotaR:   .int  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22
           .int  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20
           .int  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23
           .int  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21

tbConstH:            .int 0x67452301       // H0
                     .int 0xEFCDAB89       // H1
                     .int 0x98BADCFE       // H2
                     .int 0x10325476       // H3
 
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
//iNbBlocs:                    .skip 8
sZoneConv:                   .skip 24
sZoneResult:                 .skip 24
tbH:                         .skip 4 * 4         // 4 variables H
sZoneTrav:                   .skip ZWORKSIZE
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                      // entry of program 
 
    ldr x0,qAdrszMessTest1
    bl computeExemple
 
    ldr x0,qAdrszMessTest2
    bl computeExemple
    
    ldr x0,qAdrszMessTest3
    bl computeExemple

    ldr x0,qAdrszMessTest4
    bl computeExemple
    
    ldr x0,qAdrszMessTest5
    bl computeExemple
 
    ldr x0,qAdrszMessFinPgm
    bl affichageMess                       // display message
 
 
100:                                       // standard end of the program 
    mov x0,0                               // return code
    mov x8,EXIT                            // request to exit program
    svc 0                                  // perform the system call
 
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrszMessResult:         .quad szMessResult
qAdrszMessResult1:         .quad szMessResult1
qAdrszMessRosetta:        .quad szMessRosetta
qAdrszMessTest1:          .quad szMessTest1
qAdrszMessTest2:          .quad szMessTest2
qAdrszMessTest3:          .quad szMessTest3
qAdrszMessTest4:          .quad szMessTest4
qAdrszMessTest5:          .quad szMessTest5
qAdrsZoneTrav:            .quad sZoneTrav
qAdrsZoneConv:            .quad sZoneConv
qAdrszMessFinPgm:         .quad szMessFinPgm
/***********************************************/
/*     compute exemple                         */ 
/***********************************************/
/* x0 contains the address of the message */
computeExemple:
    stp x18,lr,[sp,-16]!      // save  registers
    mov x18,x0
    bl computeMD5             // call routine MD5
 
    ldr x0,qAdrszMessResult
    bl affichageMess
    mov x0,x18
    bl affichageMess  
    ldr x0,qAdrszMessResult1
    bl affichageMess
    ldr x0, qAdrsZoneResult
    bl displayMD5
    
100:
    ldp x18,lr,[sp],16        // restaur  2 registers
    ret                       // return to address lr x30
/******************************************************************/
/*     compute MD5                         */ 
/******************************************************************/
/* x0 contains the address of the message */
computeMD5:
    stp x1,lr,[sp,-16]!       // save  registers
    ldr x1,qAdrsZoneTrav
    mov x2,#0                // counter length 
1:                           // copy string in work area
    cmp x2,ZWORKSIZE
    bge 99f
    ldrb w3,[x0,x2]
    strb w3,[x1,x2]
    cmp x3,#0
    add x4,x2,1
    csel x2,x4,x2,ne
    bne 1b
                             // add bit et compute length
    lsl x6,x2,#3             // initial message length in bits 
    mov x3,#0b10000000       // add bit 1 at end of string
    strb w3,[x1,x2]
    add x2,x2,#1             // length in bytes
    lsl x4,x2,#3             // length in bits
    mov x3,#0
2:
    lsr x5,x2,#6             // padding block 512 bytes 
    lsl x5,x5,#6
    sub x5,x2,x5
    cmp x5,#56
    beq 3f                   // yes -> end add
    strb w3,[x1,x2]          // add zero at message end
    add x2,x2,#1             // increment length bytes 
    add x4,x4,#8             // increment length in bits
    b 2b
3:
    str x6,[x1,x2]           // and store at end    
    
    ldr x7,qAdrtbConstH      // constantes H address
    ldr x4,qAdrtbH           // start area H
    mov x5,#0
4:                           // init array H with start constantes
    ldr w6,[x7,x5,lsl #2]    // load constante
    str w6,[x4,x5,lsl #2]    // and store
    add x5,x5,#1
    cmp x5,#4                // constantes number
    blt 4b
    
                             // split into block of 64 bytes
    add x2,x2,#4             //  TODO : à revoir
    lsr x4,x2,#6             // blocks number
    mov x7,#0                // no de block et x1 contient l'adresse zone de travail
    ldr x3,qAdrtbConstK      // K constantes  address
    ldr x5,qAdrtbRotaR       // R rotation address
    
5:                           // begin loop of each block of 64 bytes
                             // init variable a b c d with H0 H1 H2 H3
    ldr x0,qAdrtbH
    ldr w8,[x0]              // a
    ldr w9,[x0,#4]           // b
    ldr w10,[x0,#8]          // c
    ldr w11,[x0,#12]         // d

    mov x6,#0                // indice t
                             /* x2  address begin each block */
    ldr x1,qAdrsZoneTrav
    add x2,x1,x7,lsl #6      //  compute block begin  indice * 4 * 16
6:                           // begin loop one 
    cmp x6,15
    bgt 7f
                             // cas 1 f := (b et c) ou ((non b) et d)
                             //   g := i
    and w12,w9,w10
    mvn w13,w9
    and w13,w13,w11
    orr w12,w12,w13        // f
    mov x14,x6             // g
    b 10f
7:
    cmp x6,31
    bgt 8f
                           //  f := (d et b) ou ((non d) et c)
                           // g := (5×i + 1) mod 16
    and w12,w11,w9
    mvn w13,w11
    and w13,w13,w10
    orr w12,w12,w13        // f
    mov x13,5
    mul x13,x6,x13
    add x13,x13,1
    lsr x15,x13,4
    lsl x15,x15,4
    sub x14,x13,x15
    b 10f
8:
    cmp x6,47
    bgt 9f
                           // f := b xor c xor d
                           // g := (3×i + 5) mod 16
    eor w12,w9,w10
    eor w12,w12,w11
    mov x13,3
    mul x13,x6,x13
    add x13,x13,5
    lsr x15,x13,4
    lsl x15,x15,4
    sub x14,x13,x15
    
    b 10f
9:
                           // f := c xor (b ou (non d))
                           //  g := (7×i) mod 16
    mvn w13,w11
    orr w13,w13,w9 
    eor w12,w13,w10        // f
    mov x13,7
    mul x13,x6,x13
    lsr x15,x13,4
    lsl x15,x15,4
    sub x14,x13,x15       // g

10:
    mov w15,w11
    mov w11,w10              // d = c
    mov w10,w9               // c = b
    add w16,w8,w12           // a + f
    ldr w17,[x2,x14,lsl #2]
    add w16,w16,w17          // + valeur bloc g
    ldr w13,[x3,x6,lsl #2]
    add w16,w16,w13          // + valeur constante K de i
    ldr w17,[x5,x6,lsl #2]   // rotate left value
    mov w13,32
    sub w17,w13,w17
    ror w13,w16,w17
    add w9,w9,w13            // new b
    mov w8, w15              // new a 
    
    add x6,x6,1
    cmp x6,63
    ble 6b
    
    ldr x0,qAdrtbH
    ldr w1,[x0]                // H0
    add w1,w1,w8               // + a
    str w1,[x0]
    ldr w1,[x0,#4]             // H1
    add w1,w1,w9               // + b
    str w1,[x0,#4]
    ldr w1,[x0,#8]             // H2
    add w1,w1,w10              // + c
    str w1,[x0,#8]
    ldr w1,[x0,#12]            // H3
    add w1,w1,w11              // + d
    str w1,[x0,#12]
                               // other bloc
    add x7,x7,1                // increment block
    cmp x7,x4                  // maxi ?
    ble 5b
    
                               // compute final result
    ldr x0,qAdrtbH             // start area H
    ldr x2,qAdrsZoneResult
    ldr w1,[x0]
    str w1,[x2]
    ldr w1,[x0,#4]
    str w1,[x2,#4]
    ldr w1,[x0,#8]
    str w1,[x2,#8]
    ldr w1,[x0,#12]
    str w1,[x2,#12]
 
    mov x0,#0                    // routine OK
    b 100f
99:                              // size error
    ldr x0,qAdrszMessSizeError
    bl affichageMess
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrtbConstH:             .quad tbConstH
qAdrtbConstK:             .quad tbConstK
qAdrtbRotaR:              .quad tbRotaR
qAdrtbH:                  .quad tbH
qAdrsZoneResult:          .quad sZoneResult
qAdrszMessSizeError:      .quad szMessSizeError

/******************************************************************/
/*     display hash  MD5                         */ 
/******************************************************************/
/* x0 contains the address of hash  */
displayMD5:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    mov x3,x0
    mov x2,#0
1:
    ldr w0,[x3,x2,lsl #2]          // load 4 bytes
    rev w0,w0                      // reverse bytes
    ldr x1,qAdrsZoneConv
    bl conversion16_4W             // conversion hexa
    ldr x0,qAdrsZoneConv
    bl affichageMess
    add x2,x2,#1
    cmp x2,#MD5_DIGEST_LENGTH / 4
    blt 1b                         // and loop
    ldr x0,qAdrszCarriageReturn
    bl affichageMess               // display message
100:
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/******************************************************************/
/*     conversion  hexadecimal register 32 bits                   */ 
/******************************************************************/
/* x0 contains value and x1 address zone receptrice   */
conversion16_4W:
    stp x0,lr,[sp,-48]!        // save  registres
    stp x1,x2,[sp,32]          // save  registres
    stp x3,x4,[sp,16]          // save  registres
    mov x2,#28                 // start bit position
    mov x4,#0xF0000000         // mask
    mov x3,x0                  // save entry value
1:                             // start loop
    and x0,x3,x4               // value register and mask
    lsr x0,x0,x2               // right shift
    cmp x0,#10                 // >= 10 ?
    bge 2f                     // yes
    add x0,x0,#48              // no is digit
    b 3f
2:
    add x0,x0,#55              // else is a letter A-F
3:
    strb w0,[x1],#1            // load result  and + 1 in address
    lsr x4,x4,#4               // shift mask 4 bits left
    subs x2,x2,#4              // decrement counter 4 bits <= zero  ?
    bge 1b                     // no -> loop
 
100:                           // fin standard de la fonction
    ldp x3,x4,[sp,16]          // restaur des  2 registres
    ldp x1,x2,[sp,32]          // restaur des  2 registres
    ldp x0,lr,[sp],48          // restaur des  2 registres
    ret    
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
Result for  => D41D8CD98F00B204E9800998ECF8427E
Result for abc => 900150983CD24FB0D6963F7D28E17F72
Result for abcdefghijklmnopqrstuvwxyz => C3FCD3D76192E4007DFB496CCA67E13B
Result for 12345678901234567890123456789012345678901234567890123456789012345678901234567890 => 57EDF4A22BE3C955AC49DA2E2107B67A
Result for ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 => D174AB98D277D9F5A5611C2C9F419D9F
Program End ok.

Ada

Works with: GNAT
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;

ALGOL 68

# Based on wikipedia article pseudocode #

# s specifies the per-round shift amounts #
[]INT s = (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);

[]BITS k = (16rd76aa478, 16re8c7b756, 16r242070db, 16rc1bdceee,
	    16rf57c0faf, 16r4787c62a, 16ra8304613, 16rfd469501,
	    16r698098d8, 16r8b44f7af, 16rffff5bb1, 16r895cd7be,
	    16r6b901122, 16rfd987193, 16ra679438e, 16r49b40821,
	    16rf61e2562, 16rc040b340, 16r265e5a51, 16re9b6c7aa,
	    16rd62f105d, 16r02441453, 16rd8a1e681, 16re7d3fbc8,
	    16r21e1cde6, 16rc33707d6, 16rf4d50d87, 16r455a14ed,
	    16ra9e3e905, 16rfcefa3f8, 16r676f02d9, 16r8d2a4c8a,
	    16rfffa3942, 16r8771f681, 16r6d9d6122, 16rfde5380c,
	    16ra4beea44, 16r4bdecfa9, 16rf6bb4b60, 16rbebfbc70,
	    16r289b7ec6, 16reaa127fa, 16rd4ef3085, 16r04881d05,
	    16rd9d4d039, 16re6db99e5, 16r1fa27cf8, 16rc4ac5665,
	    16rf4292244, 16r432aff97, 16rab9423a7, 16rfc93a039,
	    16r655b59c3, 16r8f0ccc92, 16rffeff47d, 16r85845dd1,
	    16r6fa87e4f, 16rfe2ce6e0, 16ra3014314, 16r4e0811a1,
	    16rf7537e82, 16rbd3af235, 16r2ad7d2bb, 16reb86d391);

OP + = (BITS a, b) BITS:
   BEGIN
      BITS c = BIN (ABS (a AND 16rffff) + ABS (b AND 16rffff));
      BITS d = BIN (ABS (a SHR 16) + ABS (b SHR 16) + ABS (c SHR 16));
      (c AND 16rffff) OR (d SHL 16)
   END;

#[0:63]LONG INT k;
FOR i FROM 0 TO 63 DO 
   k[i] :=  ENTIER (ABS (sin(i+1)) * LONG INT(2)**32)
OD;#

PROC md5 = (STRING intext) STRING:
   BEGIN 
      # Initialize variables: #
      BITS a0 := 16r67452301,
           a1 := 16refcdab89,
           a2 := 16r98badcfe,
           a3 := 16r10325476;

      STRING text := intext;
 
      # Pre-processing: adding a single 1 bit #
      text +:= REPR 128;
 
      # Pre-processing: padding with zeros
        append "0" bit until message length in bits ≡ 448 (mod 512) #
      WHILE ELEMS text MOD 64 ≠ 56 DO 
         text +:= REPR 0
      OD;
 
      # append original length in bits mod (2 pow 64) to message #
      text +:= dec2asc (ELEMS intext * 8);
 
      # MD5 rounds #
      # Process the message in successive 512-bit chunks: #
      WHILE text ≠ "" DO 
	 # for each 512-bit (64 byte) chunk of message #
	 []CHAR chunk = text[1:64]; text := text[65:];
	 # break chunk into sixteen 32-bit words M[j], 0 <= j <= 15 #
	 [0:15]BITS m;
         FOR j FROM 0 TO 15 DO 
             m[j] := BIN (ABS chunk[j*4+1]) OR 
	             BIN (ABS chunk[j*4+2]) SHL 8 OR 
	             BIN (ABS chunk[j*4+3]) SHL 16 OR 
	             BIN (ABS chunk[j*4+4]) SHL 24
          OD;
          INT g;
	  BITS a, b, c, d, f, dtemp;

	  # Initialize hash value for this chunk #
	  a := a0;
          b := a1;
          c := a2;
          d := a3;
          FOR i FROM 0 TO 63 DO 
             IF 0 <= i AND i <= 15 THEN
		f := (b AND c) OR ((NOT b) AND d);
		g := i
	     ELIF 16 <= i AND i <= 31 THEN 
		 f := (d AND b) OR ((NOT d) AND c);
		 g := (5×i + 1) MOD 16
	     ELIF 32 <= i AND i <= 47 THEN 
		 f := b XOR c XOR d;
		 g := (3×i + 5) MOD 16
	     ELIF 48 <= i AND i <= 63 THEN 
		 f := c XOR (b OR (NOT d));
		 g := (7×i) MOD 16
	     FI;
	     dtemp := d;
	     d := c;
	     c := b;
	     b := b + leftrotate ((a + f + k[1+i] + m[g]), s[1+i]);
	     a := dtemp
          OD;
	  # Add this chunk's hash to result so far #
          a0 := a0 + a;
          a1 := a1 + b;
          a2 := a2 + c;
          a3 := a3 + d
       OD;
       revhex (a0) + revhex (a1) + revhex (a2) + revhex (a3)
    END;

PROC leftrotate = (BITS x, INT c) BITS:
    (x SHL c) OR (x SHR (32-c));
  
# dec2asc: dec to 8 byte asc #
PROC dec2asc = (INT nn)STRING:
   BEGIN
      STRING h := ""; INT n := nn;
      FOR i TO 8 DO 
         h +:= REPR (n MOD 256);
         n ÷:= 256
      OD;
      h
   END;

 PROC revhex = (BITS x) STRING :
   BEGIN # Convert to lowercase hexadecimal STRING #
      PROC hexdig = (BITS x) CHAR: (REPR (ABS(x) <= 9 | ABS(x) + ABS("0") | ABS(x) - 10 + ABS("a")));
      hexdig (x SHR 4 AND 16rf) +
      hexdig (x AND 16rf) +
      hexdig (x SHR 12 AND 16rf) +
      hexdig (x SHR 8 AND 16rf) +
      hexdig (x SHR 20 AND 16rf) +
      hexdig (x SHR 16 AND 16rf) +
      hexdig (x SHR 28 AND 16rf) +
      hexdig (x SHR 24 AND 16rf)
   END;

STRING testmsg = "The quick brown fox jumps over the lazy dog";
STRING checksum = "9e107d9d372bb6826bd81d3542a419d6";
 
print ((testmsg, new line));
print ((checksum, new line));
 
STRING test = md5 (testmsg);

IF test = checksum THEN
   print (("passed", new line));
   print ((test, new line))
ELSE
   print (("failed"))
FI

APL

Works with: Dyalog APL
 md5{
     ⍝ index origin zero
     ⎕IO0
     ⍝ decoding UTF-8 & padding
     M(⊢,(0512|448-512|≢))1,l,⍉(82)'UTF-8'⎕UCS 
     ⍝ add length
     M,,⍉(82)⊤⌽(8256)⊤≢l
     ⍝ init registers
     A166 7 4 5 2 3 0 1
     B1614 15 12 13 10 11 8 9
     C169 8 11 10 13 12 15 14
     D161 0 3 2 5 4 7 6
     ⍝ T table
     T(2*32)×|11+⍳64
     ⍝ index table
     K16|i,(1+5×i),(5+3×i),7×i16
     ⍝ rot table
     S,1 0 24 4 47 12 17 22 5 9 14 20 4 11 16 23 6 10 15 21
     ⍝ truncate ⍵ to 32 bit & rot left ⍺
     rot{2(322)}
     proc{
         ⍝ pack 512 bits into 32 bit words &
         ⍝ precompute X[k] + T[i]
         lT+(K)256⊥⍉⌽16 42⊥⍉64 8
         fn{
         ⍝ a b c d to binary
             a b c d↓⍉(322)
         ⍝ a + F(b,c,d)
             <16:S[]rot l[]+2a+dbcd
             <32:S[]rot l[]+2a+(bd)(c∧~d)
             <48:S[]rot l[]+2a+bcd
             S[]rot l[]+2a+cb∨~d
         }
         (2*32)|+⊃{¯1(([1]+ fn )@0)}/(⌽⍳64),⊂
     }
     ⍝ process each 512 bits
     loop{⍺:⍵  (512)(512)proc }
     ⍝ output registers
     (⎕D,⎕A)[,⍉(216)⊤,⍉⊖(4256)M loop A B C D]
 }

Arturo

print digest "The quick brown fox jumped over the lazy dog's back"
Output:
e38ca1d920c4b8b8d3946b2c72f01680

ARM Assembly

Works with: as version Raspberry Pi
or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program MD5.s   */

/* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess conversion10 
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

.equ LGHASH, 16                  // result length 
.equ ZWORKSIZE,        1000      // work area size

/*******************************************/
/* Structures                               */
/********************************************/
/* example structure  variables  */
    .struct  0
var_a:                     // a
    .struct  var_a + 4
var_b:                     // b
    .struct  var_b + 4
var_c:                     // c
    .struct  var_c + 4
var_d:                     // d
    .struct  var_d + 4
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessTest1:           .asciz "abc" 
szMessTest4:           .asciz "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
szMessTest2:           .asciz "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
szMessTest3:           .asciz "abcdefghijklmnopqrstuvwxyz"
szMessFinPgm:          .asciz "Program End ok.\n"
szMessResult:          .asciz "Result for "
szMessResult1:         .asciz " => "
szMessSizeError:       .asciz "\033[31mWork area too small !! \033[0m \n"
szCarriageReturn:   .asciz "\n"

.align 4
/* array constantes K */
tbConstK:  .int 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee
           .int 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501
           .int 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be
           .int 0x6b901122,0xfd987193,0xa679438e,0x49b40821
           .int 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa
           .int 0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8
           .int 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed
           .int 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a
           .int 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c
           .int 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70
           .int 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05
           .int 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665
           .int 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039
           .int 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1
           .int 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1
           .int 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391  

/* array rotation coef R */
tbRotaR:   .int  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22
           .int  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20
           .int  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23
           .int  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21

tbConstH:            .int 0x67452301       // H0
                     .int 0xEFCDAB89       // H1
                     .int 0x98BADCFE       // H2
                     .int 0x10325476       // H3

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:                   .skip 24
tbH:                         .skip 4 * 4         @ 4 variables H
tbabcd:                      .skip 4 * 4         @ 4 variables a b c d
sZoneTrav:                   .skip 1000
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                           @ entry of program 
                      
    ldr r0,iAdrszMessTest1
    bl computeExemple
    
    ldr r0,iAdrszMessTest2
    bl computeExemple
    
    ldr r0,iAdrszMessTest3
    bl computeExemple
    
    ldr r0,iAdrszMessTest4
    bl computeExemple

    ldr r0,iAdrszMessFinPgm
    bl affichageMess            @ display message


100:                            @ standard end of the program 
    mov r0, #0                  @ return code
    mov r7, #EXIT               @ request to exit program
    svc #0                      @ perform the system call
 
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessResult:         .int szMessResult
iAdrszMessResult1:        .int szMessResult1
iAdrszMessTest1:          .int szMessTest1
iAdrszMessTest2:          .int szMessTest2
iAdrszMessTest3:          .int szMessTest3
iAdrszMessTest4:          .int szMessTest4
iAdrsZoneTrav:            .int sZoneTrav
iAdrsZoneConv:            .int sZoneConv
iAdrszMessFinPgm:         .int szMessFinPgm
iAdrszMessSizeError:      .int szMessSizeError
/***********************************************/
/*     compute exemple                         */ 
/***********************************************/
/* r0 contains the address of the message */
computeExemple:
    push {r1,lr}         @ save  registres
    mov r1,r0
    bl computeMD5        @ call routine MD5
 
    ldr r0,iAdrszMessResult
    bl affichageMess
    mov r0,r1
    bl affichageMess  
    ldr r0,iAdrszMessResult1
    bl affichageMess
    ldr r0, iAdrtbH
    bl displayMD5
    
100:
    pop {r1,pc}           @ restaur registers

/******************************************************************/
/*     compute MD5                         */ 
/******************************************************************/
/* r0 contains the address of the message */
computeMD5:
    push {r1-r12,lr}         @ save  registres
    ldr r1,iAdrsZoneTrav
    mov r2,#0                @ counter length 
1:                           @ copy string in work area
    cmp r2,#ZWORKSIZE        @ maxi ?
    bge 99f                  @ error
    ldrb r3,[r0,r2]
    strb r3,[r1,r2]
    cmp r3,#0                    
    addne r2,r2,#1
    bne 1b
    lsl r6,r2,#3             @ initial message length in bits 
    mov r3,#0b10000000       @ add bit 1 at end of string
    strb r3,[r1,r2]
    add r2,r2,#1             @ length in bytes
    lsl r4,r2,#3             @ length in bits
    mov r3,#0
2:
    lsr r5,r2,#6
    lsl r5,r5,#6
    sub r5,r2,r5
    cmp r5,#56
    beq 3f                   @ yes -> end add
    strb r3,[r1,r2]          @ add zero at message end
    add r2,#1                @ increment lenght bytes 
    add r4,#8                @ increment length in bits
    b 2b
3:
    str r6,[r1,r2]           @ and store length at end
    add r5,r2,#4
    str r3,[r1,r5]           @ store zero in hight bits for 64 bits

    ldr r7,iAdrtbConstH      @ constantes H address
    ldr r4,iAdrtbH           @ start area H
    mov r5,#0
4:                           @ init array H with start constantes
    ldr r6,[r7,r5,lsl #2]    @ load constante
    str r6,[r4,r5,lsl #2]    @ and store
    add r5,r5,#1
    cmp r5,#4
    blt 4b
                             @ split into block of 64 bytes
    add r2,#4                @  TODO : à revoir
    lsr r4,r2,#6             @ blocks number

    ldr r0,iAdrtbH             @ variables H
    ldr r1,iAdrsZoneTrav
    ldr r5,iAdrtbConstK
    ldr r3,iAdrtbRotaR
    ldr r8,iAdrtbabcd
    mov r7,#0                @ n° de block et r1 contient l adresse zone de travail
5:                           @ begin loop of each block of 64 bytes
    add r2,r1,r7,lsl #6            @  compute block begin  indice * 4 * 16
    mov r6,#0                @ indice t
   /* COMPUTING THE MESSAGE DIGEST */
    /* r0  variables H address */
    /* r1  work area  */
    /* r2  block work area begin address  */
    /* r3  address constantes rotate */
    /* r4  block number  */
    /* r5  constance K address */
    /* r6  counter t */
    /* r7  block counter */
    /* r8  addresse variables a b c d   */
                                   @ init variable a b c d with variables H
    mov r10,#0
6:                                 @ loop init
    ldr r9,[r0,r10,lsl #2]         @ variables H
    str r9,[r8,r10,lsl #2]         @ variables a b c d
    add r10,r10,#1
    cmp r10,#4
    blt 6b
    
7:                                 @ loop begin
    cmp r6,#15
    bgt 8f
                                   @ cas 1 f := (b et c) ou ((non b) et d)
                                   @ g := i
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_c]
    and r12,r10,r9
    mvn r9,r9
    ldr r10,[r8,#var_d]
    and r11,r9,r10
    orr r12,r12,r11                @ f
    mov r9,r6                      @ g
    b 11f
8:
    cmp r6,#31
    bgt 9f
                                   @ f := (d et b) ou ((non d) et c)
                                   @ g := (5×i + 1) mod 16
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_d]
    and r12,r10,r9
    mvn r10,r10
    ldr r9,[r8,#var_c]
    and r11,r9,r10
    orr r12,r12,r11                @ f
    mov r9,#5
    mul r9,r6,r9
    add r9,r9,#1
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g
    
    b 11f
9:
    cmp r6,#47
    bgt 10f
                                   @ f := b xor c xor d
                                   @ g := (3×i + 5) mod 16
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_c]
    eor r12,r10,r9
    ldr r10,[r8,#var_d]
    eor r12,r12,r10                @ f
    mov r9,#3
    mul r9,r6,r9
    add r9,r9,#5
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g
    b 11f
10:
                                   @ f := c xor (b ou (non d))
                                   @ g := (7×i) mod 16
    ldr r10,[r8,#var_d]
    mvn r12,r10
    ldr r10,[r8,#var_b] 
    orr r12,r12,r10
    ldr r10,[r8,#var_c] 
    eor r12,r12,r10                @ f
    mov r9,#7
    mul r9,r6,r9
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g
    
11:
    ldr r10,[r8,#var_d]
    mov r11,r10                    @ save old d
    ldr r10,[r8,#var_c]
    str r10,[r8,#var_d]            @ new d = c
    ldr r10,[r8,#var_b]
    str r10,[r8,#var_c]            @ new c = b
    ldr r10,[r8,#var_a]
    add r12,r12,r10                @ a + f
    ldr r10,[r2,r9,lsl #2] 
    add r12,r12,r10                @ + valeur bloc g
    ldr r10,[r5,r6,lsl #2]
    add r12,r12,r10                @ + valeur constante K de i
    ldr r10,[r3,r6,lsl #2]         @ rotate left value
    rsb r10,r10,#32                @ compute right rotate
    ror r12,r12,r10
    ldr r10,[r8,#var_b]
    add r12,r12,r10
    str r12,[r8,#var_b]            @ new b
    str r11,[r8,#var_a]            @ new a = old d
    
    add r6,r6,#1
    cmp r6,#63
    ble 7b
                                   @ maj area H
    ldr r10,[r0]                   @ H0
    ldr r11,[r8,#var_a]
    add r10,r10,r11                @ + a
    str r10,[r0]
    ldr r10,[r0,#4]                @ H1
    ldr r11,[r8,#var_b]
    add r10,r10,r11                @ + b
    str r10,[r0,#4]
    ldr r10,[r0,#8]                @ H2
    ldr r11,[r8,#var_c]
    add r10,r10,r11                @ + c
    str r10,[r0,#8]
    ldr r10,[r0,#12]               @ H3
    ldr r11,[r8,#var_d]
    add r10,r10,r11                @ + d
    str r10,[r0,#12]
 
                                 @ loop other block
    add r7,r7,#1                 @ increment block
    cmp r7,r4                    @ maxi ?
    ble 5b
    
    mov r9,#0                    @ reverse bytes loop
12:
    ldr r10,[r0,r9,lsl #2]
    rev r10,r10                  @ reverse bytes
    str r10,[r0,r9,lsl #2]
    add r9,r9,#1
    cmp r9,#LGHASH / 4
    blt 12b
    mov r0,#0                    @ routine OK
    b 100f
99:                              @ size error
    ldr r0,iAdrszMessSizeError
    bl affichageMess
    mov r0,#-1                   @ error routine
    
100:
    pop {r1-r12,pc}              @ restaur registers
iAdrtbConstH:        .int tbConstH
iAdrtbConstK:        .int tbConstK
iAdrtbRotaR:         .int tbRotaR
iAdrtbH:             .int tbH
iAdrtbabcd:          .int tbabcd

/*************************************************/
/*     display hash  MD5                         */ 
/*************************************************/
/* r0 contains the address of hash  */
displayMD5:
    push {r1-r3,lr}                @ save  registres
    mov r3,r0
    mov r2,#0
1:
    ldr r0,[r3,r2,lsl #2]          @ load 4 bytes
    ldr r1,iAdrsZoneConv
    bl conversion16                @ conversion hexa
    ldr r0,iAdrsZoneConv
    bl affichageMess
    add r2,r2,#1
    cmp r2,#LGHASH / 4
    blt 1b                         @ and loop
    ldr r0,iAdrszCarriageReturn
    bl affichageMess               @ display message
100:
    pop {r1-r3,lr}                 @ restaur registers
    bx lr                          @ return  
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Result for abc => 900150983CD24FB0D6963F7D28E17F72
Result for ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 => D174AB98D277D9F5A5611C2C9F419D9F
Result for abcdefghijklmnopqrstuvwxyz => C3FCD3D76192E4007DFB496CCA67E13B
Result for 12345678901234567890123456789012345678901234567890123456789012345678901234567890 => 57EDF4A22BE3C955AC49DA2E2107B67A
Program End ok.

AutoHotkey

Search autohotkey.com: [1]

Regular version

Source: AutoHotkey forum by SKAN

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 
}

Native implementation

Source: AutoHotkey forum by Laszlo

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

BaCon

PRAGMA INCLUDE <stdio.h>
PRAGMA INCLUDE <stdlib.h>
PRAGMA INCLUDE <string.h>
PRAGMA INCLUDE <openssl/md5.h>
PRAGMA LDFLAGS -lcrypto -lm -w 

DECLARE result TYPE unsigned char *
DECLARE string TYPE const char *

string = "Rosetta code"
strlenght = LEN(string)

result = MD5( string, strlenght , 0)
 
FOR  i = 0 TO MD5_DIGEST_LENGTH-1
    PRINT   result[i] FORMAT "%02x"
NEXT


BASIC256

print MD5("")
print MD5("a")
print MD5("abc")
print MD5("message digest")
print MD5("abcdefghijklmnopqrstuvwxyz")
print MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
print MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
end
Output:
d41d8cd98f00b204e9800998ecf8427e
0cc175b9c0f1b6a831c399e269772661
900150983cd24fb0d6963f7d28e17f72
f96b697d7cb7938d525a2f31aaf161d0
c3fcd3d76192e4007dfb496cca67e13b
d174ab98d277d9f5a5611c2c9f419d9f
57edf4a22be3c955ac49da2e2107b67a


BBC BASIC

See MD5/Implementation for a native version.

      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$

C

Library: OpenSSL
#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;
}

Implementation of md5 (Needs review - differences observed for the last 8 characters when compared with openssl implementation)

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

    if( msg2 )
        free( msg2 );

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

C#

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());

C++

Library: Poco Crypto
#include <string>
#include <iostream>
#include "Poco/MD5Engine.h"
#include "Poco/DigestStream.h"

using Poco::DigestEngine ;
using Poco::MD5Engine ;
using Poco::DigestOutputStream ;

int main( ) {
   std::string myphrase ( "The quick brown fox jumped over the lazy dog's back" ) ;
   MD5Engine md5 ;
   DigestOutputStream outstr( md5 ) ;
   outstr << myphrase ;
   outstr.flush( ) ; //to pass everything to the digest engine
   const DigestEngine::Digest& digest = md5.digest( ) ;
   std::cout << myphrase << " as a MD5 digest :\n" << DigestEngine::digestToHex( digest ) 
      << " !" << std::endl ;
   return 0 ;
}
Output:
The quick brown fox jumped over the lazy dog's back as a MD5 digest :
e38ca1d920c4b8b8d3946b2c72f01680 !

Caché ObjectScript

USER>set hash=$System.Encryption.MD5Hash("The quick brown fox jumped over the lazy dog's back")
USER>zzdump hash
0000: E3 8C A1 D9 20 C4 B8 B8 D3 94 6B 2C 72 F0 16 80

Clojure

(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"))))))

COBOL

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MD5.
       AUTHOR.  Bill Gunshannon
       INSTALLATION.  Home.
       DATE-WRITTEN.  16 December 2021.
      ************************************************************
      ** Program Abstract:
      **   Use the md5sum utility and pass the HASH back using
      **     a temp file.  Not elegant, but it works.
      ************************************************************
       
       
       ENVIRONMENT DIVISION.
       
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
            SELECT Tmp-MD5 ASSIGN TO "/tmp/MD5"
                 ORGANIZATION IS LINE SEQUENTIAL.


       DATA DIVISION.

       FILE SECTION.
       
       FD  Tmp-MD5
           DATA RECORD IS MD5-Rec.
       01  MD5-Rec       PIC X(32).

       
       WORKING-STORAGE SECTION.
       
       01 Eof                   PIC X     VALUE 'F'.
       01 Str1.
          05  Pre-cmd   PIC X(8)
              VALUE 'echo -n '.
          05  Str1-complete.
              10  Str1-Part1  PIC X(26)
                  VALUE  'The quick brown fox jumps'.
              10  Str1-Part2  PIC X(19)
                  VALUE  ' over the lazy dog'.
          05  Post-cmd    PIC X(20)
              VALUE  ' | md5sum > /tmp/MD5'.
       01  Str1-MD5          PIC X(32).
       
       
       PROCEDURE DIVISION.
       
       Main-Program.

           DISPLAY Str1-complete.
           PERFORM Get-MD5.
           DISPLAY Str1-MD5.

           STOP RUN.

       Get-MD5.
       
           CALL "SYSTEM" USING Str1.
           OPEN INPUT Tmp-MD5.
           READ Tmp-MD5 INTO Str1-MD5.
           CLOSE Tmp-MD5.
           CALL "CBL_DELETE_FILE" USING '/tmp/MD5'.
 
       IDENTIFICATION DIVISION.
       PROGRAM-ID. MD5-DEMO.
       AUTHOR.  Bill Gunshannon
       INSTALLATION.  Home.
       DATE-WRITTEN.  16 December 2021.
      ************************************************************
      ** Program Abstract:
      **   Use the md5sum utility and pass the HASH back using
      **     a temp file.  Not elegant, but it works.
      **   Same program but made MD5 a User Defined Function
      **     instead of a procedure.
      ************************************************************
 
 
       ENVIRONMENT DIVISION.
 
       CONFIGURATION SECTION.

       REPOSITORY.
          FUNCTION MD5.

       DATA DIVISION.
 
       WORKING-STORAGE SECTION.
 
       01 Eof                   PIC X     VALUE 'F'.
       01 Str1.
          05  Pre-cmd   PIC X(8)
              VALUE 'echo -n '.
          05  Str1-complete.
              10  Str1-Part1  PIC X(26)
                  VALUE  'The quick brown fox jumps'.
              10  Str1-Part2  PIC X(19)
                  VALUE  ' over the lazy dog'.
          05  Post-cmd    PIC X(20)
              VALUE  ' | md5sum > /tmp/MD5'.
       01  Str1-MD5          PIC X(32).
 
 
       PROCEDURE DIVISION.
 
       Main-Program.
 
           DISPLAY Str1-complete.
      *    PERFORM Get-MD5.
           MOVE FUNCTION MD5(Str1) TO Str1-MD5.
           DISPLAY Str1-MD5.
 
           STOP RUN.

        END PROGRAM MD5-DEMO.
 
       IDENTIFICATION DIVISION.
       FUNCTION-ID. MD5.

       ENVIRONMENT DIVISION.

       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
            SELECT Tmp-MD5 ASSIGN TO "/tmp/MD5"
                 ORGANIZATION IS LINE SEQUENTIAL.


       DATA DIVISION.

       FILE SECTION.

       FD  Tmp-MD5
           DATA RECORD IS MD5-Rec.
       01  MD5-Rec       PIC X(32).



       LINKAGE SECTION.
       01  Str1        PIC X(128).
       01  Str1-MD5    PIC X(32).

       PROCEDURE DIVISION USING Str1 RETURNING Str1-MD5.
 
           CALL "SYSTEM" USING FUNCTION TRIM(Str1).
           OPEN INPUT Tmp-MD5.
           READ Tmp-MD5 INTO Str1-MD5.
           CLOSE Tmp-MD5.
           CALL "CBL_DELETE_FILE" USING '/tmp/MD5'.
           GO-BACK. 

        END FUNCTION MD5.
Output:
The quick brown fox jumps  over the lazy dog 
9e107d9d372bb6826bd81d3542a419d6

Common Lisp

Library: Ironclad
(ql:quickload 'ironclad)
(defun md5 (str)
  (ironclad:byte-array-to-hex-string
    (ironclad:digest-sequence :md5 
                              (ironclad:ascii-string-to-byte-array str))))
(defvar *tests* '("" 
                  "a"
                  "abc"
                  "message digest"
                  "abcdefghijklmnopqrstuvwxyz"
                  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
                  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"))
(dolist (msg *tests*)
  (format T "~s: ~a~%" msg (md5 msg)))
Output:
"": d41d8cd98f00b204e9800998ecf8427e
"a": 0cc175b9c0f1b6a831c399e269772661
"abc": 900150983cd24fb0d6963f7d28e17f72
"message digest": f96b697d7cb7938d525a2f31aaf161d0
"abcdefghijklmnopqrstuvwxyz": c3fcd3d76192e4007dfb496cca67e13b
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789": d174ab98d277d9f5a5611c2c9f419d9f
"12345678901234567890123456789012345678901234567890123456789012345678901234567890": 57edf4a22be3c955ac49da2e2107b67a
Another method using openssl:
Library: CFFI
(cffi:load-foreign-library "libcrypto.so")

(cffi:defcfun ("MD5" MD5) :void (string :string) (len :int) (ptr :pointer))

(let ((string-to-convert "The quick brown fox jumped over the lazy dog's back")
      (ptr (cffi:foreign-alloc :unsigned-char :count 16)))
  (md5 string-to-convert (length string-to-convert) ptr)
  (loop for i from 0 below 16 do
       (format t "~a" (write-to-string (cffi:mem-ref ptr :unsigned-char i) :base 16)))
  (cffi:foreign-free ptr))
Output:
E38CA1D920C4B8B8D3946B2C72F01680

Crystal

require "digest/md5"

puts Digest::MD5.hexdigest("The quick brown fox jumped over the lazy dog's back")
Output:
e38ca1d920c4b8b8d3946b2c72f01680

D

void main() {
    import std.stdio, std.digest.md;

    auto txt = "The quick brown fox jumped over the lazy dog's back";
    writefln("%-(%02x%)", txt.md5Of);
}
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Alternative version:

Library: Tango
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());
  }
}

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.

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.

Output:

D41D8CD98F00B204E9800998ECF8427E
0CC175B9C0F1B6A831C399E269772661
900150983CD24FB0D6963F7D28E17F72
F96B697D7CB7938D525A2F31AAF161D0
C3FCD3D76192E4007DFB496CCA67E13B
D174AB98D277D9F5A5611C2C9F419D9F
57EDF4A22BE3C955AC49DA2E2107B67A

DuckDB

SELECT MD5('The quick brown fox jumped over the lazy dog''s back') as md5;
Output:
┌──────────────────────────────────┐
│               md5                │
│             varchar              │
├──────────────────────────────────┤
│ e38ca1d920c4b8b8d3946b2c72f01680 │
└──────────────────────────────────┘

E

Works with: E-on-Java
Translation of: Java

(with modifications)

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

EasyLang

len md5k[] 64
proc md5init . .
   for i = 1 to 64
      md5k[i] = floor (0x100000000 * abs sin (i * 180 / pi))
   .
.
md5init
# 
func$ md5 inp$ .
   subr addinp
      if inp4 = 1
         inp[] &= 0
      .
      inp[len inp[]] += b * inp4
      inp4 *= 0x100
      if inp4 = 0x100000000
         inp4 = 1
      .
   .
   s[] = [ 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 ]
   inp[] = [ ]
   inp4 = 1
   for i = 1 to len inp$
      b = strcode substr inp$ i 1
      addinp
   .
   b = 0x80
   addinp
   while len inp[] mod 16 <> 14 or inp4 <> 1
      b = 0
      addinp
   .
   h = len inp$ * 8
   for i = 1 to 4
      b = h mod 0x100
      addinp
      h = h div 0x100
   .
   inp[] &= 0
   # 
   a0 = 0x67452301
   b0 = 0xefcdab89
   c0 = 0x98badcfe
   d0 = 0x10325476
   for chunk = 1 step 16 to len inp[] - 15
      a = a0 ; b = b0 ; c = c0 ; d = d0
      for i = 1 to 64
         if i <= 16
            h1 = bitand b c
            h2 = bitand bitnot b d
            f = bitor h1 h2
            g = i - 1
         elif i <= 32
            h1 = bitand d b
            h2 = bitand bitnot d c
            f = bitor h1 h2
            g = (5 * i - 4) mod 16
         elif i <= 48
            h1 = bitxor b c
            f = bitxor h1 d
            g = (3 * i + 2) mod 16
         else
            h1 = bitor b bitnot d
            f = bitxor c h1
            g = (7 * i - 7) mod 16
         .
         f = (f + a + md5k[i] + inp[chunk + g])
         a = d
         d = c
         c = b
         h1 = bitshift f s[i]
         h2 = bitshift f (s[i] - 32)
         b = (b + h1 + h2)
      .
      a0 += a ; b0 += b ; c0 += c ; d0 += d
   .
   for a in [ a0 b0 c0 d0 ]
      for i = 1 to 4
         b = a mod 256
         a = a div 256
         for h in [ b div 16 b mod 16 ]
            h += 48
            if h > 57
               h += 39
            .
            s$ &= strchar h
         .
      .
   .
   return s$
.
#
print md5 "The quick brown fox jumped over the lazy dog's back"
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Emacs Lisp

(md5 "The quick brown fox jumped over the lazy dog's back") ;=> "e38ca1d920c4b8b8d3946b2c72f01680"
(secure-hash 'md5 "The quick brown fox jumped over the lazy dog's back") ;=> "e38ca1d920c4b8b8d3946b2c72f01680"

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:

-module(tests).
-export([md5/1]).

md5(S) ->
 string:to_upper(
  lists:flatten([io_lib:format("~2.16.0b",[N]) || <<N>> <= erlang:md5(S)])
 ).

Testing it:

1> c(tests).
{ok,tests}
2> tests:md5("The quick brown fox jumped over the lazy dog's back").
"E38CA1D920C4B8B8D3946B2C72F01680"

F#

Using built-in System.Security.Cryptography.MD5 class (Link to original blog [2]).

let md5ootb (msg: string) =
  use md5 = System.Security.Cryptography.MD5.Create()
  msg
  |> System.Text.Encoding.ASCII.GetBytes
  |> md5.ComputeHash
  |> Seq.map (fun c -> c.ToString("X2"))
  |> Seq.reduce ( + )

md5ootb @"The quick brown fox jumped over the lazy dog's back"

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

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

Fortran

Intel Fortran on Windows

Using Windows API. See CryptAcquireContextA, CryptCreateHash, CryptHashData and CryptGetHashParam in Microsoft documentation.

module md5_mod
    use kernel32
    use advapi32
    implicit none
    integer, parameter :: MD5LEN = 16
contains
    subroutine md5hash(name, hash, dwStatus, filesize)
        implicit none
        character(*) :: name
        integer, parameter :: BUFLEN = 32768
        integer(HANDLE) :: hFile, hProv, hHash
        integer(DWORD) :: dwStatus, nRead
        integer(BOOL) :: status
        integer(BYTE) :: buffer(BUFLEN)
        integer(BYTE) :: hash(MD5LEN)
        integer(UINT64) :: filesize
 
        dwStatus = 0
        filesize = 0
        hFile = CreateFile(trim(name) // char(0), GENERIC_READ, FILE_SHARE_READ, NULL, &
                           OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)
 
        if (hFile == INVALID_HANDLE_VALUE) then
            dwStatus = GetLastError()
            print *, "CreateFile failed."
            return
        end if
 
        if (CryptAcquireContext(hProv, NULL, NULL, PROV_RSA_FULL, &
                                CRYPT_VERIFYCONTEXT) == FALSE) then
            dwStatus = GetLastError()
            print *, "CryptAcquireContext failed."
            goto 3
        end if
 
        if (CryptCreateHash(hProv, CALG_MD5, 0_ULONG_PTR, 0_DWORD, hHash) == FALSE) then
            dwStatus = GetLastError()
            print *, "CryptCreateHash failed."
            go to 2
        end if
 
        do
            status = ReadFile(hFile, loc(buffer), BUFLEN, nRead, NULL)
            if (status == FALSE .or. nRead == 0) exit
            filesize = filesize + nRead
            if (CryptHashData(hHash, buffer, nRead, 0) == FALSE) then
                dwStatus = GetLastError()
                print *, "CryptHashData failed."
                go to 1
            end if
        end do
 
        if (status == FALSE) then
            dwStatus = GetLastError()
            print *, "ReadFile failed."
            go to 1
        end if
 
        nRead = MD5LEN
        if (CryptGetHashParam(hHash, HP_HASHVAL, hash, nRead, 0) == FALSE) then
            dwStatus = GetLastError()
            print *, "CryptGetHashParam failed.", status, nRead, dwStatus
        end if
 
      1 status = CryptDestroyHash(hHash)
      2 status = CryptReleaseContext(hProv, 0)
      3 status = CloseHandle(hFile)
    end subroutine
end module
 
program md5
    use md5_mod
    implicit none
    integer :: n, m, i, j
    character(:), allocatable :: name
    integer(DWORD) :: dwStatus
    integer(BYTE) :: hash(MD5LEN)
    integer(UINT64) :: filesize
 
    n = command_argument_count()
    do i = 1, n
        call get_command_argument(i, length=m)
        allocate(character(m) :: name)
        call get_command_argument(i, name)
        call md5hash(name, hash, dwStatus, filesize)
        if (dwStatus == 0) then
            do j = 1, MD5LEN
                write(*, "(Z2.2)", advance="NO") hash(j)
            end do
            write(*, "(' ',A,' (',G0,' bytes)')") name, filesize
        end if
        deallocate(name)
    end do
end program

FreeBASIC

See MD5/Implementation#FreeBASIC

Frink

The function messageDigest[string, hash] returns a hex-encoded hash of any input string with a variety of hashing functions.

println[messageDigest["The quick brown fox", "MD5"]]

Futhark

Real languages roll their own crypto.

type md5 = (u32, u32, u32, u32)

fun rs(): [64]u32 =
  map u32
  ([ 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 ])

fun ks(): [64]u32 =
  map u32
  ([ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
     0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
     0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
     0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
     0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
     0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
     0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
     0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
     0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
     0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
     0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
     0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
     0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
     0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
     0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ])

fun md5(ms: [n][16]u32): md5 =
  let a0 = u32(0x67452301)
  let b0 = u32(0xefcdab89)
  let c0 = u32(0x98badcfe)
  let d0 = u32(0x10325476)
  loop ((a0,b0,c0,d0)) = for i < n do
    let (a,b,c,d) = md5_chunk (a0,b0,c0,d0) ms[i]
    in (a0+a, b0+b, c0+c, d0+d)
  in (a0,b0,c0,d0)

fun rotate_left(x: u32, c: u32): u32 = (x << c) | (x >> (32u32 - c))

fun bytes(x: u32): [4]u8 = [u8(x),
                            u8(x/0x100u32),
                            u8(x/0x10000u32),
                            u8(x/0x1000000u32)]

fun unbytes(bs: [4]u8): u32 =
  u32(bs[0]) +
  u32(bs[1]) * 0x100u32 +
  u32(bs[2]) * 0x10000u32 +
  u32(bs[3]) * 0x1000000u32

fun unbytes_block(block: [64]u8): [16]u32 =
  map unbytes (reshape (16,4) block)

fun main(ms: [n]u8): [16]u8 =
  let padding = 64 - (n % 64)
  let n_padded = n + padding
  let ms_padded = concat ms (bytes 0x80u32) (replicate (padding-12) 0x0u8) (bytes (u32(n*8))) ([0u8,0u8,0u8,0u8])
  let (a,b,c,d) = md5 (map unbytes_block (reshape (n_padded / 64, 64) ms_padded))
  in reshape 16 (map bytes ([a,b,c,d]))

-- Process 512 bits of the input.
fun md5_chunk ((a0,b0,c0,d0): md5) (m: [16]u32): md5 =
  loop ((a,b,c,d) = (a0,b0,c0,d0)) = for i < 64 do
    let (f,g) =
      if      i < 16 then ((b & c) | ((~b) & d),
                           i)
      else if i < 32 then ((d & b) | ((~d) & c),
                           i32((5u32*u32(i) + 1u32) % 16u32))
      else if i < 48 then (b ^ c ^ d,
                           i32((3u32*u32(i) + 5u32) % 16u32))
      else                (c ^ (b | (~d)),
                           i32((7u32*u32(i))        % 16u32))
    in (d, b + rotate_left(a + f + (ks())[i] + m[g], (rs())[i]), b, c)
  in (a,b,c,d)

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

Groovy

import java.security.MessageDigest

String.metaClass.md5Checksum = {
    MessageDigest.getInstance('md5').digest(delegate.bytes).collect { String.format("%02x", it) }.join('')
}

Testing

assert 'The quick brown fox jumps over the lazy dog'.md5Checksum() == '9e107d9d372bb6826bd81d3542a419d6'

Haskell

Use modules nano-MD5 and ByteString from HackageDB

import Data.Digest.OpenSSL.MD5 (md5sum)
import Data.ByteString (pack)
import Data.Char (ord)

main = do
  let message = "The quick brown fox jumped over the lazy dog's back"
      digest  = (md5sum . pack . map (fromIntegral . ord)) message
  putStrLn digest

Use in GHCi:

*Main> main
e38ca1d920c4b8b8d3946b2c72f01680

This version uses the Cryptonite package:

Library: Cryptonite
#!/usr/bin/env runhaskell

import Data.ByteString.Char8 (pack)
import System.Environment (getArgs)
import Crypto.Hash

main :: IO ()
main = print . md5 . pack . unwords =<< getArgs
         where md5 x = hash x :: Digest MD5
Output:
$ ./md5.hs The quick brown fox jumped over the lazy dog\'s back
e38ca1d920c4b8b8d3946b2c72f01680

Haxe

import haxe.crypto.Md5;

class Main {
  static function main() {	
    var md5 = Md5.encode("The quick brown fox jumped over the lazy dog's back");
    Sys.println(md5);
  }
}
Output:
e38ca1d920c4b8b8d3946b2c72f01680

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.

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

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

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

J

Using the md5 script from the convert/misc addon package:

   require 'convert/misc/md5'
   md5 'The quick brown fox jumped over the lazy dog''s back'
e38ca1d920c4b8b8d3946b2c72f01680

Implementation here, in case the link to the script goes dead again:

require 'convert'

'`lt gt ge xor'=: (20 b.)`(18 b.)`(27 b.)`(22 b.)
'`and or sh'=: (17 b.)`(23 b.)`(33 b.)

{{
if. IF64 do.
rot=: (16bffffffff and sh or ] sh~ 32 -~ [) NB. (y << x) | (y >>> (32 - x))
add=: ((16bffffffff&and)@+)"0
else.
rot=: (32 b.)
add=: (+&(_16&sh) (16&sh@(+ _16&sh) or and&65535@]) +&(and&65535))"0
end.
EMPTY
}}''

hexlist=: tolower@:,@:hfd@:,@:(|."1)@(256 256 256 256&#:)

cmn=: {{
'x s t'=. x [ 'q a b'=. y
b add s rot (a add q) add (x add t)
}}

ff=: cmn (((1&{ and 2&{) or 1&{ lt 3&{) , 2&{.)
gg=: cmn (((1&{ and 3&{) or 2&{ gt 3&{) , 2&{.)
hh=: cmn (((1&{ xor 2&{)xor 3&{       ) , 2&{.)
ii=: cmn (( 2&{ xor 1&{  ge 3&{       ) , 2&{.)
op=: ff`gg`hh`ii

I=: ".;._2{{)n
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 6 11 0 5 10 15 4 9 14 3 8 13 2 7 12
5 8 11 14 1 4 7 10 13 0 3 6 9 12 15 2
0 7 14 5 12 3 10 1 8 15 6 13 4 11 2 9
}}
S=: 4 4$7 12 17 22 5 9 14 20 4 11 16 23 6 10 15 21

T=: |:".;._2{{)n
 _680876936  _165796510     _378558  _198630844
 _389564586 _1069501632 _2022574463  1126891415
  606105819   643717713  1839030562 _1416354905
_1044525330  _373897302   _35309556   _57434055
 _176418897  _701558691 _1530992060  1700485571
 1200080426    38016083  1272893353 _1894986606
_1473231341  _660478335  _155497632    _1051523
  _45705983  _405537848 _1094730640 _2054922799
 1770035416   568446438   681279174  1873313359
_1958414417 _1019803690  _358537222   _30611744
     _42063  _187363961  _722521979 _1560198380
_1990404162  1163531501    76029189  1309151649
 1804603682 _1444681467  _640364487  _145523070
  _40341101   _51403784  _421815835 _1120210379
_1502002290  1735328473   530742520   718787259
 1236535329 _1926607734  _995338651  _343485551
}}

norm=: {{
N=. 16 * 1 + _6 sh 8 + #y
b=. N#0  [  y=. a.i.y
for_i. i. #y do.
  b=. ((j { b) or (8*4|i) sh i{y) (j=. _2 sh i) } b
end.
b=. ((j { b) or (8*4|i) sh 128) (j=._2 sh i=.#y) } b
_16]\ (8 * #y) (N-2) } b
}}

md5=: {{
X=. norm y
q=. r=. 1732584193 _271733879 _1732584194 271733878
for_k. X do.
  for_j. i.4 do.
    l=. ((j{I){k) ,. (16$j{S) ,. j{T
    for_i. i.16 do.
      r=. _1|.((i{l) (op@.j) r),}.r
    end.
  end.
  q=. r=. r add q
end.
hexlist r
}}

An alternative and faster approach is to use the Qt library function available using the ide/qt addon from J8:

   require '~addons/ide/qt/qt.ijs'
   getmd5=: 'md5'&gethash_jqtide_
   getmd5 'The quick brown fox jumped over the lazy dog''s back'
e38ca1d920c4b8b8d3946b2c72f01680

Java

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Digester {

    public static void main(String[] args) {
        System.out.println(hexDigest("Rosetta code", "MD5"));
    }

    static String hexDigest(String str, String digestName) {
        try {
            MessageDigest md = MessageDigest.getInstance(digestName);
            byte[] digest = md.digest(str.getBytes(StandardCharsets.UTF_8));
            char[] hex = new char[digest.length * 2];
            for (int i = 0; i < digest.length; i++) {
                hex[2 * i] = "0123456789abcdef".charAt((digest[i] & 0xf0) >> 4);
                hex[2 * i + 1] = "0123456789abcdef".charAt(digest[i] & 0x0f);
            }
            return new String(hex);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e);
        }
    }
}

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 "UTF_8" in the example above) are available from the Charset and StandardCharsets classes.

Jsish

/* MD5 hash in Jsish */
var str = 'Rosetta code';
puts(Util.hash(str, {type:'md5'}));

/* MD5 RFC1321 test suite */
function MD5(str) { return Util.hash(str, {type:'md5'}); }

;MD5('');
;MD5('a');
;MD5('abc');
;MD5('message digest');
;MD5('abcdefghijklmnopqrstuvwxyz');
;MD5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
;MD5('12345678901234567890123456789012345678901234567890123456789012345678901234567890');

/*
=!EXPECTSTART!=
bf0ac9c7e94e9d50c18f4ff592643546
MD5('') ==> d41d8cd98f00b204e9800998ecf8427e
MD5('a') ==> 0cc175b9c0f1b6a831c399e269772661
MD5('abc') ==> 900150983cd24fb0d6963f7d28e17f72
MD5('message digest') ==> f96b697d7cb7938d525a2f31aaf161d0
MD5('abcdefghijklmnopqrstuvwxyz') ==> c3fcd3d76192e4007dfb496cca67e13b
MD5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') ==> d174ab98d277d9f5a5611c2c9f419d9f
MD5('12345678901234567890123456789012345678901234567890123456789012345678901234567890') ==> 57edf4a22be3c955ac49da2e2107b67a
=!EXPECTEND!=
*/
Output:
prompt$ jsish md5.jsi
bf0ac9c7e94e9d50c18f4ff592643546

prompt$ jsish --U md5.jsi               # display unit test echos 
bf0ac9c7e94e9d50c18f4ff592643546
MD5('') ==> d41d8cd98f00b204e9800998ecf8427e
MD5('a') ==> 0cc175b9c0f1b6a831c399e269772661
MD5('abc') ==> 900150983cd24fb0d6963f7d28e17f72
MD5('message digest') ==> f96b697d7cb7938d525a2f31aaf161d0
MD5('abcdefghijklmnopqrstuvwxyz') ==> c3fcd3d76192e4007dfb496cca67e13b
MD5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') ==> d174ab98d277d9f5a5611c2c9f419d9f
MD5('12345678901234567890123456789012345678901234567890123456789012345678901234567890') ==> 57edf4a22be3c955ac49da2e2107b67a

prompt$ jsish -u md5.jsi               # run the unit tests
[PASS] md5.jsi

Julia

Works with: Julia version 0.6
using Nettle

function Base.trunc(s::AbstractString, n::Integer)
    n > 0 || throw(DomainError())
    l = length(s)
    l > n || return s
    n > 3 || return s[1:n]
    return s[1:n-3] * "..."
end

tests = [""    => "d41d8cd98f00b204e9800998ecf8427e",
         "a"   => "0cc175b9c0f1b6a831c399e269772661",
         "abc" => "900150983cd24fb0d6963f7d28e17f72",
         "message digest" => "f96b697d7cb7938d525a2f31aaf161d0",
         "abcdefghijklmnopqrstuvwxyz" => "c3fcd3d76192e4007dfb496cca67e13b",
         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" =>
         "d174ab98d277d9f5a5611c2c9f419d9f",
         "12345678901234567890123456789012345678901234567890123456789012345678901234567890" =>
         "57edf4a22be3c955ac49da2e2107b67a",
         "foobad" => "3858f62230ac3c915f300c664312c63f"]

println("Testing Julia's MD5 hash against RFC 1321.")
for (k, h) in sort(tests, by = length  first)
    md5sum = hexdigest("md5", k)
    @printf("%20s%s ", trunc(k, 15), md5sum)
    if md5sum == h
        println("MD5 OK")
    else
        println("MD5 Bad")
        println("* The sum should be  ", h)
    end
end
Output:
                     → d41d8cd98f00b204e9800998ecf8427e MD5 OK
                   a → 0cc175b9c0f1b6a831c399e269772661 MD5 OK
                 abc → 900150983cd24fb0d6963f7d28e17f72 MD5 OK
              foobad → 6ce0d31e08fc3c4de8e3b2fa0d3d72ff MD5 Bad
* The sum should be  3858f62230ac3c915f300c664312c63f
      message digest → f96b697d7cb7938d525a2f31aaf161d0 MD5 OK
     abcdefghijkl... → c3fcd3d76192e4007dfb496cca67e13b MD5 OK
     ABCDEFGHIJKL... → d174ab98d277d9f5a5611c2c9f419d9f MD5 OK
     123456789012... → 57edf4a22be3c955ac49da2e2107b67a MD5 O

Kotlin

// version 1.0.6

import java.security.MessageDigest

fun main(args: Array<String>) {
    val text  = "The quick brown fox jumped over the lazy dog's back"
    val bytes = text.toByteArray()
    val md = MessageDigest.getInstance("MD5")
    val digest = md.digest(bytes)
    for (byte in digest) print("%02x".format(byte))
    println() 
}
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Lasso

Encrypt_MD5('Welcome all Rhinos!')
//80ba88ee2600e9e9b36e739458c39ebd

Test suite

local(test = map(
		'a' = '0cc175b9c0f1b6a831c399e269772661',
		'abc' = '900150983cd24fb0d6963f7d28e17f72',
		'message digest' = 'f96b697d7cb7938d525a2f31aaf161d0',
		'abcdefghijklmnopqrstuvwxyz' = 'c3fcd3d76192e4007dfb496cca67e13b',
		'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' = 'd174ab98d277d9f5a5611c2c9f419d9f',
		'12345678901234567890123456789012345678901234567890123456789012345678901234567890' = '57edf4a22be3c955ac49da2e2107b67a'
	)
)
with a in #test->keys do =>  {^
	'testing: "'+#a+'": '+(Encrypt_MD5(#a)->asBytes == #test->find(#a)->asBytes)+'\r'
^}
Output:
testing: "12345678901234567890123456789012345678901234567890123456789012345678901234567890": true
testing: "a": true
testing: "abc": true
testing: "abcdefghijklmnopqrstuvwxyz": true
testing: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789": true
testing: "message digest": true

Liberty BASIC

'[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

Lingo

  • Using a binary plugin ("Xtra"):
Library: Crypto Xtra
put cx_md5_string(str)
  • Pure Lingo implementation
----------------------------------------
-- Calculates MD5 hash of string or bytearray
-- @param {bytearray|string} input
-- @return {bytearray} (16 bytes)
----------------------------------------
on md5 (input)
  if stringP(input) then input = bytearray(input)

  -- Convert string to list of little-endian words...
  t_iLen = input.length * 8
  t_iCnt = (t_iLen + 64) / 512 * 16 + 16

  -- Create list, fill with zeros...
  x = []
  x[t_iCnt] = 0

  t_fArr = [1, 256, 65536, 16777216]
  i = 0
  j = 0
  repeat while i < t_iLen
    j = j + 1
    t_iNext = i / 32 + 1
    t_iTemp = bitAnd(input[i/8+1], 255) * t_fArr[j]
    x[t_iNext] = bitOr(x[t_iNext], t_iTemp)
    i = i + 8
    j = j mod 4
  end repeat

  -- Append padding...
  t_iNext = t_iLen / 32 + 1
  x[t_iNext] = bitOr(x[t_iNext], 128 * t_fArr[j + 1])
  x[(t_iLen + 64) / 512 * 16 + 15] = t_iLen

  -- Actual algorithm starts here...
  a =  1732584193
  b = -271733879
  c = -1732584194
  d =  271733878
  i =  1
  t_iWrap = the maxInteger + 1
  t_iCount = x.count + 1

  repeat while i < t_iCount
    olda = a
    oldb = b
    oldc = c
    oldd = d

    -- Round(1) --
    n = bitOr(bitAnd(b, c), bitAnd(bitNot(b), d)) + a + x[i] - 680876936
    if(n < 0) then a = bitOr(n * 128, bitOr((n + t_iWrap) / 33554432, 64)) + b
    else a = bitOr(n * 128, n / 33554432) + b
    n = bitOr(bitAnd(a, b), bitAnd(bitNot(a), c)) + d + x[i + 1] - 389564586
    if(n < 0) then d = bitOr(n * 4096, bitOr((n + t_iWrap) / 1048576, 2048)) + a
    else d = bitOr(n * 4096, n / 1048576) + a
    n = bitOr(bitAnd(d, a), bitAnd(bitNot(d), b)) + c + x[i + 2] + 606105819
    if(n < 0) then c = bitOr(n * 131072, bitOr((n + t_iWrap) / 32768, 65536)) + d
    else c = bitOr(n * 131072, n / 32768) + d
    n = bitOr(bitAnd(c, d), bitAnd(bitNot(c), a)) + b + x[i + 3] - 1044525330
    if(n < 0) then b = bitOr(n * 4194304, bitOr((n + t_iWrap) / 1024, 2097152)) + c
    else b = bitOr(n * 4194304, n / 1024) + c
    n = bitOr(bitAnd(b, c), bitAnd(bitNot(b), d)) + a + x[i + 4] - 176418897
    if(n < 0) then a = bitOr(n * 128, bitOr((n + t_iWrap) / 33554432, 64)) + b
    else a = bitOr(n * 128, n / 33554432) + b
    n = bitOr(bitAnd(a, b), bitAnd(bitNot(a), c)) + d + x[i + 5] + 1200080426
    if(n < 0) then d = bitOr(n * 4096, bitOr((n + t_iWrap) / 1048576, 2048)) + a
    else d = bitOr(n * 4096, n / 1048576) + a
    n = bitOr(bitAnd(d, a), bitAnd(bitNot(d), b)) + c + x[i + 6] - 1473231341
    if(n < 0) then c = bitOr(n * 131072, bitOr((n + t_iWrap) / 32768, 65536)) + d
    else c = bitOr(n * 131072, n / 32768) + d
    n = bitOr(bitAnd(c, d), bitAnd(bitNot(c), a)) + b + x[i + 7] - 45705983
    if(n < 0) then b = bitOr(n * 4194304, bitOr((n + t_iWrap) / 1024, 2097152)) + c
    else b = bitOr(n * 4194304, n / 1024) + c
    n = bitOr(bitAnd(b, c), bitAnd(bitNot(b), d)) + a + x[i + 8] + 1770035416
    if(n < 0) then a = bitOr(n * 128, bitOr((n + t_iWrap) / 33554432, 64)) + b
    else a = bitOr(n * 128, n / 33554432) + b
    n = bitOr(bitAnd(a, b), bitAnd(bitNot(a), c)) + d + x[i + 9] - 1958414417
    if(n < 0) then d = bitOr(n * 4096, bitOr((n + t_iWrap) / 1048576, 2048)) + a
    else d = bitOr(n * 4096, n / 1048576) + a
    n = bitOr(bitAnd(d, a), bitAnd(bitNot(d), b)) + c + x[i + 10] - 42063
    if(n < 0) then c = bitOr(n * 131072, bitOr((n + t_iWrap) / 32768, 65536)) + d
    else c = bitOr(n * 131072, n / 32768) + d
    n = bitOr(bitAnd(c, d), bitAnd(bitNot(c), a)) + b + x[i + 11] - 1990404162
    if(n < 0) then b = bitOr(n * 4194304, bitOr((n + t_iWrap) / 1024, 2097152)) + c
    else b = bitOr(n * 4194304, n / 1024) + c
    n = bitOr(bitAnd(b, c), bitAnd(bitNot(b), d)) + a + x[i + 12] + 1804603682
    if(n < 0) then a = bitOr(n * 128, bitOr((n + t_iWrap) / 33554432, 64)) + b
    else a = bitOr(n * 128, n / 33554432) + b
    n = bitOr(bitAnd(a, b), bitAnd(bitNot(a), c)) + d + x[i + 13] - 40341101
    if(n < 0) then d = bitOr(n * 4096, bitOr((n + t_iWrap) / 1048576, 2048)) + a
    else d = bitOr(n * 4096, n / 1048576) + a
    n = bitOr(bitAnd(d, a), bitAnd(bitNot(d), b)) + c + x[i + 14] - 1502002290
    if(n < 0) then c = bitOr(n * 131072, bitOr((n + t_iWrap) / 32768, 65536)) + d
    else c = bitOr(n * 131072, n / 32768) + d
    n = bitOr(bitAnd(c, d), bitAnd(bitNot(c), a)) + b + x[i + 15] + 1236535329
    if(n < 0) then b = bitOr(n * 4194304, bitOr((n + t_iWrap) / 1024, 2097152)) + c
    else b = bitOr(n * 4194304, n / 1024) + c

    -- Round(2) --
    n = bitOr(bitAnd(b, d), bitAnd(c, bitNot(d))) + a + x[i + 1] - 165796510
    if(n < 0) then a = bitOr(n * 32, bitOr((n + t_iWrap) / 134217728, 16)) + b
    else a = bitOr(n * 32, n / 134217728) + b
    n = bitOr(bitAnd(a, c), bitAnd(b, bitNot(c))) + d + x[i + 6] - 1069501632
    if(n < 0) then d = bitOr(n * 512, bitOr((n + t_iWrap) / 8388608, 256)) + a
    else d = bitOr(n * 512, n / 8388608) + a
    n = bitOr(bitAnd(d, b), bitAnd(a, bitNot(b))) + c + x[i + 11] + 643717713
    if(n < 0) then c = bitOr(n * 16384, bitOr((n + t_iWrap) / 262144, 8192)) + d
    else c = bitOr(n * 16384, n / 262144) + d
    n = bitOr(bitAnd(c, a), bitAnd(d, bitNot(a))) + b + x[i] - 373897302
    if(n < 0) then b = bitOr(n * 1048576, bitOr((n + t_iWrap) / 4096, 524288)) + c
    else b = bitOr(n * 1048576, n / 4096) + c
    n = bitOr(bitAnd(b, d), bitAnd(c, bitNot(d))) + a + x[i + 5] - 701558691
    if(n < 0) then a = bitOr(n * 32, bitOr((n + t_iWrap) / 134217728, 16)) + b
    else a = bitOr(n * 32, n / 134217728) + b
    n = bitOr(bitAnd(a, c), bitAnd(b, bitNot(c))) + d + x[i + 10] + 38016083
    if(n < 0) then d = bitOr(n * 512, bitOr((n + t_iWrap) / 8388608, 256)) + a
    else d = bitOr(n * 512, n / 8388608) + a
    n = bitOr(bitAnd(d, b), bitAnd(a, bitNot(b))) + c + x[i + 15] - 660478335
    if(n < 0) then c = bitOr(n * 16384, bitOr((n + t_iWrap) / 262144, 8192)) + d
    else c = bitOr(n * 16384, n / 262144) + d
    n = bitOr(bitAnd(c, a), bitAnd(d, bitNot(a))) + b + x[i + 4] - 405537848
    if(n < 0) then b = bitOr(n * 1048576, bitOr((n + t_iWrap) / 4096, 524288)) + c
    else b = bitOr(n * 1048576, n / 4096) + c
    n = bitOr(bitAnd(b, d), bitAnd(c, bitNot(d))) + a + x[i + 9] + 568446438
    if(n < 0) then a = bitOr(n * 32, bitOr((n + t_iWrap) / 134217728, 16)) + b
    else a = bitOr(n * 32, n / 134217728) + b
    n = bitOr(bitAnd(a, c), bitAnd(b, bitNot(c))) + d + x[i + 14] - 1019803690
    if(n < 0) then d = bitOr(n * 512, bitOr((n + t_iWrap) / 8388608, 256)) + a
    else d = bitOr(n * 512, n / 8388608) + a
    n = bitOr(bitAnd(d, b), bitAnd(a, bitNot(b))) + c + x[i + 3] - 187363961
    if(n < 0) then c = bitOr(n * 16384, bitOr((n + t_iWrap) / 262144, 8192)) + d
    else c = bitOr(n * 16384, n / 262144) + d
    n = bitOr(bitAnd(c, a), bitAnd(d, bitNot(a))) + b + x[i + 8] + 1163531501
    if(n < 0) then b = bitOr(n * 1048576, bitOr((n + t_iWrap) / 4096, 524288)) + c
    else b = bitOr(n * 1048576, n / 4096) + c
    n = bitOr(bitAnd(b, d), bitAnd(c, bitNot(d))) + a + x[i + 13] - 1444681467
    if(n < 0) then a = bitOr(n * 32, bitOr((n + t_iWrap) / 134217728, 16)) + b
    else a = bitOr(n * 32, n / 134217728) + b
    n = bitOr(bitAnd(a, c), bitAnd(b, bitNot(c))) + d + x[i + 2] - 51403784
    if(n < 0) then d = bitOr(n * 512, bitOr((n + t_iWrap) / 8388608, 256)) + a
    else d = bitOr(n * 512, n / 8388608) + a
    n = bitOr(bitAnd(d, b), bitAnd(a, bitNot(b))) + c + x[i + 7] + 1735328473
    if(n < 0) then c = bitOr(n * 16384, bitOr((n + t_iWrap) / 262144, 8192)) + d
    else c = bitOr(n * 16384, n / 262144) + d
    n = bitOr(bitAnd(c, a), bitAnd(d, bitNot(a))) + b + x[i + 12] - 1926607734
    if(n < 0) then b = bitOr(n * 1048576, bitOr((n + t_iWrap) / 4096, 524288)) + c
    else b = bitOr(n * 1048576, n / 4096) + c

    -- Round(3) --
    n = bitXor(bitXor(b, c), d) + a + x[i + 5] - 378558
    if(n < 0) then a = bitOr(n * 16, bitOr((n + t_iWrap) / 268435456, 8)) + b
    else a = bitOr(n * 16, n / 268435456) + b
    n = bitXor(bitXor(a, b), c) + d + x[i + 8] - 2022574463
    if(n < 0) then d = bitOr(n * 2048, bitOr((n + t_iWrap) / 2097152, 1024)) + a
    else d = bitOr(n * 2048, n / 2097152) + a
    n = bitXor(bitXor(d, a), b) + c + x[i + 11] + 1839030562
    if(n < 0) then c = bitOr(n * 65536, bitOr((n + t_iWrap) / 65536, 32768)) + d
    else c = bitOr(n * 65536, n / 65536) + d
    n = bitXor(bitXor(c, d), a) + b + x[i + 14] - 35309556
    if(n < 0) then b = bitOr(n * 8388608, bitOr((n + t_iWrap) / 512, 4194304)) + c
    else b = bitOr(n * 8388608, n / 512) + c
    n = bitXor(bitXor(b, c), d) + a + x[i + 1] - 1530992060
    if(n < 0) then a = bitOr(n * 16, bitOr((n + t_iWrap) / 268435456, 8)) + b
    else a = bitOr(n * 16, n / 268435456) + b
    n = bitXor(bitXor(a, b), c) + d + x[i + 4] + 1272893353
    if(n < 0) then d = bitOr(n * 2048, bitOr((n + t_iWrap) / 2097152, 1024)) + a
    else d = bitOr(n * 2048, n / 2097152) + a
    n = bitXor(bitXor(d, a), b) + c + x[i + 7] - 155497632
    if(n < 0) then c = bitOr(n * 65536, bitOr((n + t_iWrap) / 65536, 32768)) + d
    else c = bitOr(n * 65536, n / 65536) + d
    n = bitXor(bitXor(c, d), a) + b + x[i + 10] - 1094730640
    if(n < 0) then b = bitOr(n * 8388608, bitOr((n + t_iWrap) / 512, 4194304)) + c
    else b = bitOr(n * 8388608, n / 512) + c
    n = bitXor(bitXor(b, c), d) + a + x[i + 13] + 681279174
    if(n < 0) then a = bitOr(n * 16, bitOr((n + t_iWrap) / 268435456, 8)) + b
    else a = bitOr(n * 16, n / 268435456) + b
    n = bitXor(bitXor(a, b), c) + d + x[i] - 358537222
    if(n < 0) then d = bitOr(n * 2048, bitOr((n + t_iWrap) / 2097152, 1024)) + a
    else d = bitOr(n * 2048, n / 2097152) + a
    n = bitXor(bitXor(d, a), b) + c + x[i + 3] - 722521979
    if(n < 0) then c = bitOr(n * 65536, bitOr((n + t_iWrap) / 65536, 32768)) + d
    else c = bitOr(n * 65536, n / 65536) + d
    n = bitXor(bitXor(c, d), a) + b + x[i + 6] + 76029189
    if(n < 0) then b = bitOr(n * 8388608, bitOr((n + t_iWrap) / 512, 4194304)) + c
    else b = bitOr(n * 8388608, n / 512) + c
    n = bitXor(bitXor(b, c), d) + a + x[i + 9] - 640364487
    if(n < 0) then a = bitOr(n * 16, bitOr((n + t_iWrap) / 268435456, 8)) + b
    else a = bitOr(n * 16, n / 268435456) + b
    n = bitXor(bitXor(a, b), c) + d + x[i + 12] - 421815835
    if(n < 0) then d = bitOr(n * 2048, bitOr((n + t_iWrap) / 2097152, 1024)) + a
    else d = bitOr(n * 2048, n / 2097152) + a
    n = bitXor(bitXor(d, a), b) + c + x[i + 15] + 530742520
    if(n < 0) then c = bitOr(n * 65536, bitOr((n + t_iWrap) / 65536, 32768)) + d
    else c = bitOr(n * 65536, n / 65536) + d
    n = bitXor(bitXor(c, d), a) + b + x[i + 2] - 995338651
    if(n < 0) then b = bitOr(n * 8388608, bitOr((n + t_iWrap) / 512, 4194304)) + c
    else b = bitOr(n * 8388608, n / 512) + c

    -- Round(4) --
    n = bitXor(c, bitOr(b, bitNot(d))) + a + x[i] - 198630844
    if(n < 0) then a = bitOr(n * 64, bitOr((n + t_iWrap) / 67108864, 32)) + b
    else a = bitOr(n * 64, n / 67108864) + b
    n = bitXor(b, bitOr(a, bitNot(c))) + d + x[i + 7] + 1126891415
    if(n < 0) then d = bitOr(n * 1024, bitOr((n + t_iWrap) / 4194304, 512)) + a
    else d = bitOr(n * 1024, n / 4194304) + a
    n = bitXor(a, bitOr(d, bitNot(b))) + c + x[i + 14] - 1416354905
    if(n < 0) then c = bitOr(n * 32768, bitOr((n + t_iWrap) / 131072, 16384)) + d
    else c = bitOr(n * 32768, n / 131072) + d
    n = bitXor(d, bitOr(c, bitNot(a))) + b + x[i + 5] - 57434055
    if(n < 0) then b = bitOr(n * 2097152, bitOr((n + t_iWrap) / 2048, 1048576)) + c
    else b = bitOr(n * 2097152, n / 2048) + c
    n = bitXor(c, bitOr(b, bitNot(d))) + a + x[i + 12] + 1700485571
    if(n < 0) then a = bitOr(n * 64, bitOr((n + t_iWrap) / 67108864, 32)) + b
    else a = bitOr(n * 64, n / 67108864) + b
    n = bitXor(b, bitOr(a, bitNot(c))) + d + x[i + 3] - 1894986606
    if(n < 0) then d = bitOr(n * 1024, bitOr((n + t_iWrap) / 4194304, 512)) + a
    else d = bitOr(n * 1024, n / 4194304) + a
    n = bitXor(a, bitOr(d, bitNot(b))) + c + x[i + 10] - 1051523
    if(n < 0) then c = bitOr(n * 32768, bitOr((n + t_iWrap) / 131072, 16384)) + d
    else c = bitOr(n * 32768, n / 131072) + d
    n = bitXor(d, bitOr(c, bitNot(a))) + b + x[i + 1] - 2054922799
    if(n < 0) then b = bitOr(n * 2097152, bitOr((n + t_iWrap) / 2048, 1048576)) + c
    else b = bitOr(n * 2097152, n / 2048) + c
    n = bitXor(c, bitOr(b, bitNot(d))) + a + x[i + 8] + 1873313359
    if(n < 0) then a = bitOr(n * 64, bitOr((n + t_iWrap) / 67108864, 32)) + b
    else a = bitOr(n * 64, n / 67108864) + b
    n = bitXor(b, bitOr(a, bitNot(c))) + d + x[i + 15] - 30611744
    if(n < 0) then d = bitOr(n * 1024, bitOr((n + t_iWrap) / 4194304, 512)) + a
    else d = bitOr(n * 1024, n / 4194304) + a
    n = bitXor(a, bitOr(d, bitNot(b))) + c + x[i + 6] - 1560198380
    if(n < 0) then c = bitOr(n * 32768, bitOr((n + t_iWrap) / 131072, 16384)) + d
    else c = bitOr(n * 32768, n / 131072) + d
    n = bitXor(d, bitOr(c, bitNot(a))) + b + x[i + 13] + 1309151649
    if(n < 0) then b = bitOr(n * 2097152, bitOr((n + t_iWrap) / 2048, 1048576)) + c
    else b = bitOr(n * 2097152, n / 2048) + c
    n = bitXor(c, bitOr(b, bitNot(d))) + a + x[i + 4] - 145523070
    if(n < 0) then a = bitOr(n * 64, bitOr((n + t_iWrap) / 67108864, 32)) + b
    else a = bitOr(n * 64, n / 67108864) + b
    n = bitXor(b, bitOr(a, bitNot(c))) + d + x[i + 11] - 1120210379
    if(n < 0) then d = bitOr(n * 1024, bitOr((n + t_iWrap) / 4194304, 512)) + a
    else d = bitOr(n * 1024, n / 4194304) + a
    n = bitXor(a, bitOr(d, bitNot(b))) + c + x[i + 2] + 718787259
    if(n < 0) then c = bitOr(n * 32768, bitOr((n + t_iWrap) / 131072, 16384)) + d
    else c = bitOr(n * 32768, n / 131072) + d
    n = bitXor(d, bitOr(c, bitNot(a))) + b + x[i + 9] - 343485551
    if(n < 0) then b = bitOr(n * 2097152, bitOr((n + t_iWrap) / 2048, 1048576)) + c
    else b = bitOr(n * 2097152, n / 2048) + c
    a = a + olda
    b = b + oldb
    c = c + oldc
    d = d + oldd
    i = i + 16
  end repeat

  t_iArr = [a, b, c, d]
  ba = bytearray()
  p = 1
  repeat with i in t_iArr
    if(i > 0) then
      repeat with n = 1 to 4
        ba[p] = (i mod 256)
        i = i / 256
        p = p+1
      end repeat
    else
      i = bitNot(i)
      repeat with n = 1 to 4
        ba[p] = 255-(i mod 256)
        i = i / 256
        p = p+1
      end repeat
    end if
  end repeat
  ba.position = 1
  return ba
end

LiveCode

Livecode has built-in support for md4 and md5

function md5sum hashtext
    local md5, mdhex
    put md5Digest(hashtext) into md5
    get binaryDecode("H*",md5,mdhex)
    return mdhex
end md5sum

Tests

command md5testsuite
    //    rfc1321 MD5 test suite:
    local md5
    put md5sum("") is "d41d8cd98f00b204e9800998ecf8427e" into md5["empty"]
    put md5sum("a") is "0cc175b9c0f1b6a831c399e269772661" into md5["a"]
    put md5sum("abc") is "900150983cd24fb0d6963f7d28e17f72" into md5["abc"]
    put md5sum("message digest") is "f96b697d7cb7938d525a2f31aaf161d0" into md5["message digest"]
    put md5sum("abcdefghijklmnopqrstuvwxyz") is "c3fcd3d76192e4007dfb496cca67e13b" \
          into md5["abclower"]
    put md5sum("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") \
          is "d174ab98d277d9f5a5611c2c9f419d9f" into md5["abcupper"]
    put md5sum("12345678901234567890123456789012345678901234567890123456789012345678901234567890")\
    is "57edf4a22be3c955ac49da2e2107b67a" into md5["123"]
    
    repeat for each line n in the keys of md5
        if md5[n] is not true then
            put "err" & tab & n & return after results
            exit repeat
        else
            put "ok" & tab & n & return after results
        end if
    end repeat
    put results
end md5testsuite

Output

ok	abc
ok	abclower
ok	123
ok	abcupper
ok	message digest
ok	a
ok	empty

Lua

Using the Kepler MD5 library:

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

Maple

The Hash command in the StringTools package computes the MD5 hash value of a string.

> with( StringTools ):
> Hash( "" );
         "d41d8cd98f00b204e9800998ecf8427e"

> Hash( "a" );
         "0cc175b9c0f1b6a831c399e269772661"

> Hash( "abc" );
         "900150983cd24fb0d6963f7d28e17f72"

> Hash( "message digest" );
         "f96b697d7cb7938d525a2f31aaf161d0"

> Hash( "abcdefghijklmnopqrstuvwxyz" );
         "c3fcd3d76192e4007dfb496cca67e13b"

> Hash( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" );
         "d174ab98d277d9f5a5611c2c9f419d9f"

> Hash( "12345678901234567890123456789012345678901234567890123456789012345678901234567890" );
         "57edf4a22be3c955ac49da2e2107b67a"

Mathematica /Wolfram Language

Mathematica has built-in functions Hash and FileHash. Example:

 Hash["The quick brown fox jumped over the lazy dog's back","MD5","HexString"]

gives back:

 e38ca1d920c4b8b8d3946b2c72f01680

MATLAB

This code also works with Octave (but Octave already provides md5sum(), see Octave example).

function digest = md5(message)
    % digest = md5(message)
    %  Compute the MD5 digest of the message, as a hexadecimal digest.

    % Follow the MD5 algorithm from RFC 1321 [1] and Wikipedia [2].
    %  [1] http://tools.ietf.org/html/rfc1321
    %  [2] http://en.wikipedia.org/wiki/MD5

    % m is the modulus for 32-bit unsigned arithmetic.
    m = 2 ^ 32;

    % s is the shift table for circshift(). Each shift is negative
    % because it is a left shift.
    s = [-7, -12, -17, -22
         -5,  -9, -14, -20
         -4, -11, -16, -23
         -6, -10, -15, -21];

    % t is the sine table. Each sine is a 32-bit integer, unsigned.
    t = floor(abs(sin(1:64)) .* m);

    % Initialize the hash, as a row vector of 32-bit integers.
    digest = [hex2dec('67452301') ...
              hex2dec('EFCDAB89') ...
              hex2dec('98BADCFE') ...
              hex2dec('10325476')];

    % If message contains characters, convert them to ASCII values.
    message = double(message);
    bytelen = numel(message);

    % Pad the message by appending a 1, then appending enough 0s to make
    % the bit length congruent to 448 mod 512. Because we have bytes, we
    % append 128 '10000000', then append enough 0s '00000000's to make
    % the byte length congruent to 56 mod 64.
    message = [message, 128, zeros(1, mod(55 - bytelen, 64))];

    % Convert the message to 32-bit integers, little endian.
    % For little endian, first byte is least significant byte.
    message = reshape(message, 4, numel(message) / 4);
    message = message(1,:) + ...            % least significant byte
              message(2,:) * 256 + ...
              message(3,:) * 65536 + ...
              message(4,:) * 16777216;      % most significant byte

    % Append the bit length as a 64-bit integer, little endian.
    bitlen = bytelen * 8;
    message = [message, mod(bitlen, m), mod(bitlen / m, m)];

    % Process each 512-bit block. Because we have 32-bit integers, each
    % block has 16 elements, message(k + (0:15)).
    for k = 1:16:numel(message)
        % Copy hash.
        a = digest(1); b = digest(2); c = digest(3); d = digest(4);

        % Do 64 operations.
        for i = (1:64)
            % Convert b, c, d to row vectors of bits (0s and 1s).
            bv = dec2bin(b, 32) - '0';
            cv = dec2bin(c, 32) - '0';
            dv = dec2bin(d, 32) - '0';

            % Find f  = mix of b, c, d.
            %      ki = index in 0:15, to message(k + ki).
            %      sr = row in 1:4, to s(sr, :).
            if i <= 16          % Round 1
                f = (bv & cv) | (~bv & dv);
                ki = i - 1;
                sr = 1;
            elseif i <= 32      % Round 2
                f = (bv & dv) | (cv & ~dv);
                ki = mod(5 * i - 4, 16);
                sr = 2;
            elseif i <= 48      % Round 3
                f = xor(bv, xor(cv, dv));
                ki = mod(3 * i + 2, 16);
                sr = 3;
            else                % Round 4
                f = xor(cv, bv | ~dv);
                ki = mod(7 * i - 7, 16);
                sr = 4;
            end

            % Convert f, from row vector of bits, to 32-bit integer.
            f = bin2dec(char(f + '0'));

            % Do circular shift of sum.
            sc = mod(i - 1, 4) + 1;
            sum = mod(a + f + message(k + ki) + t(i), m);
            sum = dec2bin(sum, 32);
            sum = circshift(sum, [0, s(sr, sc)]);
            sum = bin2dec(sum);

            % Update a, b, c, d.
            temp = d;
            d = c;
            c = b;
            b = mod(b + sum, m);
            a = temp;
        end %for i

        % Add hash of this block to hash of previous blocks.
        digest = mod(digest + [a, b, c, d], m);
    end %for k

    % Convert hash from 32-bit integers, little endian, to bytes.
    digest = [digest                % least significant byte
              digest / 256
              digest / 65536
              digest / 16777216];   % most significant byte
    digest = reshape(mod(floor(digest), 256), 1, numel(digest));

    % Convert hash to hexadecimal.
    digest = dec2hex(digest);
    digest = reshape(transpose(digest), 1, numel(digest));
end %md5

Sample Usage:

octave:14> md5('Rosetta Code')
ans = CCA1BF66B09554E10F837838C3D3EFB1

min

Works with: min version 0.19.6
"The quick brown fox jumps over the lazy dog" md5 puts!

MOO

string = "The quick brown fox jumped over the lazy dog's back";
player:tell(string_hash(string));

Neko

/**
 MD5 in Neko
 Tectonics:
   nekoc md5.neko
   neko md5
*/

var MD5 = $loader.loadprim("std@make_md5", 1);
var base_encode = $loader.loadprim("std@base_encode", 2);

var result = MD5("The quick brown fox jumps over the lazy dog");

/* Output in lowercase hex */
$print(base_encode(result, "0123456789abcdef"));
Output:
prompt$ nekoc md5.neko
prompt$ neko md5.n
9e107d9d372bb6826bd81d3542a419d6

Nemerle

Translation of: C#
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))   ");
    }
}

Output:

True   True   True   True   True   True   True   True

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

  algorithm   = 'MD5'
  digestSum = getDigest(messageText, algorithm)

  say '<Message>'messageText'</Message>'
  say Rexx('<'algorithm'>').right(12) || digestSum'</'algorithm'>'
  say Rexx('<Verify>').right(12) || verifyCheck'</Verify>'
  if digestSum == verifyCheck then say algorithm 'Confirmed'
                              else say algorithm 'Failed'

  return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getDigest(messageText = Rexx, algorithm = Rexx 'MD5', encoding = Rexx 'UTF-8', lowercase = boolean 1) public static returns Rexx

  algorithm = algorithm.upper
  encoding  = encoding.upper

  message      = String(messageText)
  messageBytes = byte[]
  digestBytes  = byte[]
  digestSum    = Rexx ''

  do
    messageBytes = message.getBytes(encoding)
    md = MessageDigest.getInstance(algorithm)
    md.update(messageBytes)
    digestBytes = md.digest

    loop b_ = 0 to digestBytes.length - 1
      bb = Rexx(digestBytes[b_]).d2x(2)
      if lowercase then digestSum = digestSum || bb.lower
                   else digestSum = digestSum || bb.upper
      end b_
  catch ex = Exception
    ex.printStackTrace
  end
  
  return digestSum

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

NewLISP

;; using the crypto module from http://www.newlisp.org/code/modules/crypto.lsp.html
;; (import native functions from the crypto library, provided by OpenSSL)
(module "crypto.lsp")
(crypto:md5 "The quick brown fox jumped over the lazy dog's back")

Nim

import md5

echo toMD5("The quick brown fox jumped over the lazy dog's back")
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Nu

[
  '' 'a' 'abc' 'message digest'
  'abcdefghijklmnopqrstuvwxyz'
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  '12345678901234567890123456789012345678901234567890123456789012345678901234567890'
]
| each { hash md5 }
Output:
╭───┬──────────────────────────────────╮
│ 0 │ d41d8cd98f00b204e9800998ecf8427e │
│ 1 │ 0cc175b9c0f1b6a831c399e269772661 │
│ 2 │ 900150983cd24fb0d6963f7d28e17f72 │
│ 3 │ f96b697d7cb7938d525a2f31aaf161d0 │
│ 4 │ c3fcd3d76192e4007dfb496cca67e13b │
│ 5 │ d174ab98d277d9f5a5611c2c9f419d9f │
│ 6 │ 57edf4a22be3c955ac49da2e2107b67a │
╰───┴──────────────────────────────────╯

Oberon-2

Works with: oo2c
Library: crypto
MODULE MD5;
IMPORT
  Crypto:MD5,
  Crypto:Utils,
  Strings,
  Out;
VAR
  h: MD5.Hash;
  str: ARRAY 128 OF CHAR;
BEGIN
  h := MD5.NewHash();
  h.Initialize;
  str := "The quick brown fox jumped over the lazy dog's back";
  h.Update(str,0,Strings.Length(str));
  h.GetHash(str,0);
  Out.String("MD5: ");Utils.PrintHex(str,0,h.size);Out.Ln  
END MD5.
Output:
MD5: 
   E38CA1D9   20C4B8B8   D3946B2C   72F01680

Objeck

class MD5 {
   function : Main(args : String[]) ~ Nil {
      in := "The quick brown fox jumped over the lazy dog's back"->ToByteArray();
      hash := Encryption.Hash->MD5(in);
      hash->ToHexString()->PrintLine();
   }
}

Objective-C

Works with: GNUstep

only; not Cocoa

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]);
Works with: iPhone
Works with: Mac OS X
#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);
}
Works with: Mac OS X

(need to include "libcrypto.dylib" framework)

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

OCaml

# Digest.to_hex(Digest.string "The quick brown fox jumped over the lazy dog's back") ;;
- : string = "e38ca1d920c4b8b8d3946b2c72f01680"

Octave

s = "The quick brown fox jumped over the lazy dog's back";
hash = md5sum(s, true);
disp(hash)

For an implementation of MD5, see MATLAB example.

Ol

(import (otus ffi))
(define libcrypto (load-dynamic-library "libcrypto.so.1.0.0"))
(define MD5 (libcrypto type-vptr "MD5" type-string fft-unsigned-long type-string))
Output:
(define (test str)
    (define md5 "----------------")
    (MD5 str (string-length str) md5)
    (for-each display (list "\"" str "\": "))
    (for-each (lambda (c)
            (define hex "0123456789abcdef")
            (display (string (ref hex (>> c 4))))
            (display (string (ref hex (band c #x0F)))))
        (string->list md5))
    (print))

(test "")
(test "a")
(test "abc")
(test "message digest")
(test "abcdefghijklmnopqrstuvwxyz")
(test "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
(test "12345678901234567890123456789012345678901234567890123456789012345678901234567890")
"": d41d8cd98f00b204e9800998ecf8427e
"a": 0cc175b9c0f1b6a831c399e269772661
"abc": 900150983cd24fb0d6963f7d28e17f72
"message digest": f96b697d7cb7938d525a2f31aaf161d0
"abcdefghijklmnopqrstuvwxyz": c3fcd3d76192e4007dfb496cca67e13b
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789": d174ab98d277d9f5a5611c2c9f419d9f
"12345678901234567890123456789012345678901234567890123456789012345678901234567890": 57edf4a22be3c955ac49da2e2107b67a

OpenEdge/Progress

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.

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

Output:

---------------------------
Message
---------------------------
1 d41d8cd98f00b204e9800998ecf8427e 
2 0cc175b9c0f1b6a831c399e269772661 
3 900150983cd24fb0d6963f7d28e17f72 
4 f96b697d7cb7938d525a2f31aaf161d0 
5 c3fcd3d76192e4007dfb496cca67e13b 
6 d174ab98d277d9f5a5611c2c9f419d9f 
7 57edf4a22be3c955ac49da2e2107b67a
---------------------------
OK   
---------------------------

PARI/GP

Build a MD5 plugin using Linux system library and PARI's function interface. (Linux solution)

#include <pari/pari.h>
#include <openssl/md5.h>

#define HEX(x)  (((x) < 10)? (x)+'0': (x)-10+'a')

/*
 * PARI/GP func: MD5 hash
 *
 * gp code: install("plug_md5", "s", "MD5", "<library path>");
 */
GEN plug_md5(char *text)
{
  char md[MD5_DIGEST_LENGTH];
  char hash[sizeof(md) * 2 + 1];
  int i;

  MD5((unsigned char*)text, strlen(text), (unsigned char*)md);

  for (i = 0; i < sizeof(md); i++) {
    hash[i+i]   = HEX((md[i] >> 4) & 0x0f);
    hash[i+i+1] = HEX(md[i] & 0x0f);
  }

  hash[sizeof(md) * 2] = 0;

  return strtoGENstr(hash);
}

Compile with: gcc -Wall -O2 -fPIC -shared md5.c -o libmd5.so -lcrypt -lpari

Load plugin from your home directory into PARI:

install("plug_md5", "s", "MD5", "~/libmd5.so");

MD5("The quick brown fox jumped over the lazy dog's back")

Output:

"e38ca1d920c4b8b8d3946b2c72f01680"

Here is an explicit implementation in the PARI/GP language:

md5( message ) = { my( 
   a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476,
   s = [ 7, 12, 17, 22; 5, 9, 14, 20; 4, 11, 16, 23; 6, 10, 15, 21 ],
   msg = concat( Vec( concat(Vecsmall(message), Vecsmall(128)), (#message + 9) \ 64 * 64 + 56 ),
     Vecrev(digits( #message % 2^61 * 8, 256), 8)), \\ little endian !
   leftrotate(x, c) = x << c + x >> (32-c)
  );
  \\***  Process the message in successive 512-bit chunks ***
  forstep( m=1, #msg, 512/8, 
    my( \\ break chunk into 32-bit words M[j] - LITTLE ENDIAN !
       M = vector( 16, j, fromdigits( Vecrev(msg[ m + j*4 - 4 .. m + j*4 - 1 ]), 2^8 )),
       A = a, B = b, C = c, D = d); 
    for( i = 0 , 63 , [A, D, C, B] = [D, C, B, B + leftrotate( ( A + abs(sin(i+1))\2^-32 +
       if( i < 16 , bitor( bitand(B , C) , bitand( bitneg(B) , D)) + M[ i +1]
         , i < 32 , bitor( bitand(D , B) , bitand( bitneg(D) , C)) + M[ (5*i + 1) % 16 +1]
         , i < 48 , bitxor( bitxor( B , C ) , D ) + M[ (3*i + 5) % 16 +1]
         , bitxor( C , bitor( bitneg(D), B)) + M[ 7*i % 16 +1]
       )) % 2^32, s[i\16+1, i%4+1] )]
    ); \\ end for
    [a,b,c,d] = ([a,b,c,d] + [A,B,C,D]) % 2^32 ;
  ); \\ end forstep
  Strprintf("%032x",fromdigits(Vecrev(digits(fromdigits([d,c,b,a],2^32),256),16),256))
}

Then:

gp > md5("")
%2 = "d41d8cd98f00b204e9800998ecf8427e"
gp > md5("The quick brown fox jumps over lazy dogs.")
%3 = "4c57070257998981a0c7b7ec003b9d5c"

Pascal

Pascal has a built-in unit called md5. It can be used to get a digest both for a string and a file.

program GetMd5;

uses md5;

var
  strEncrypted : string;

begin
  strEncrypted := md5Print(md5String('The quick brown fox jumped over the lazy dog''s back'));
  writeln(strEncrypted);
end.
Output:
 e38ca1d920c4b8b8d3946b2c72f01680

To digest a file, use md5Print(md5File('myfile.txt')) where myfile.txt is a file.

Perl

use Digest::MD5 qw(md5_hex);

print md5_hex("The quick brown fox jumped over the lazy dog's back"), "\n";

The same in OO manner

use Digest::MD5;

$md5 = Digest::MD5->new;
$md5->add("The quick brown fox jumped over the lazy dog's back");
print $md5->hexdigest, "\n";

Phix

See MD5/Implementation#Phix

PHP

$string = "The quick brown fox jumped over the lazy dog's back";
echo md5( $string );

PicoLisp

Using the openssl library (the 'native' function is only in the 64-bit version available):

(let Str "The quick brown fox jumped over the lazy dog's back"
   (pack
      (mapcar '((B) (pad 2 (hex B)))
         (native "libcrypto.so" "MD5" '(B . 16) Str (length Str) '(NIL (16))) ) ) )

Output:

-> "E38CA1D920C4B8B8D3946B2C72F01680"

Pike

import String;
import Crypto.MD5;

int main(){
   write( string2hex( hash( "The quick brown fox jumped over the lazy dog's back" ) ) + "\n" );
}

PowerShell

Translation of: C#
$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()

PureBasic

Purebasic 5.x versions
UseMD5Fingerprint() ; register the MD5 fingerprint plugin

test$ = "The quick brown fox jumped over the lazy dog's back"

; Call StringFingerprint() function and display MD5 result in Debug window
Debug StringFingerprint(test$, #PB_Cipher_MD5)

Python

Using builtin libraries:

Python 3.x, 2.5 and later 2.x versions
>>> 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

>>>
Python 2.5 and later
>>> import hashlib
>>> print hashlib.md5("The quick brown fox jumped over the lazy dog's back").hexdigest()
e38ca1d920c4b8b8d3946b2c72f01680
Pre-2.5; removed in 3.x
>>> import md5
>>> print md5.md5("The quick brown fox jumped over the lazy dog's back").hexdigest()
e38ca1d920c4b8b8d3946b2c72f01680

R

library(digest)
hexdigest <- digest("The quick brown fox jumped over the lazy dog's back", 
                    algo="md5", serialize=FALSE)

Racket

#lang racket
(require file/md5)

(md5 "")
(md5 "a")
(md5 "abc")
(md5 "message digest")
(md5 "abcdefghijklmnopqrstuvwxyz")
(md5 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
(md5 "12345678901234567890123456789012345678901234567890123456789012345678901234567890")

Output:

#"d41d8cd98f00b204e9800998ecf8427e"
#"0cc175b9c0f1b6a831c399e269772661"
#"900150983cd24fb0d6963f7d28e17f72"
#"f96b697d7cb7938d525a2f31aaf161d0"
#"c3fcd3d76192e4007dfb496cca67e13b"
#"d174ab98d277d9f5a5611c2c9f419d9f"
#"57edf4a22be3c955ac49da2e2107b67a"

Raku

(formerly Perl 6) Library Digest::MD5

use Digest::MD5;
say Digest::MD5.md5_hex: "The quick brown fox jumped over the lazy dog's back";

REBOL

>> checksum/method "The quick brown fox jumped over the lazy dog" 'md5
== #{08A008A01D498C404B0C30852B39D3B8}

REXX

/*REXX program tests the MD5 procedure (below) as per a test suite the  IETF RFC (1321).*/
msg.1 =                                          /*─────MD5 test suite [from above doc].*/
msg.2 = 'a'
msg.3 = 'abc'
msg.4 = 'message digest'
msg.5 = 'abcdefghijklmnopqrstuvwxyz'
msg.6 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
msg.7 =  12345678901234567890123456789012345678901234567890123456789012345678901234567890
msg.0 = 7                                        /* [↑]  last value doesn't need quotes.*/
                do m=1  for  msg.0;       say    /*process each of the seven messages.  */
                say ' in ='  msg.m               /*display the      in      message.    */
                say 'out ='  MD5(msg.m)          /*   "     "       out        "        */
                end   /*m*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
MD5: procedure; parse arg !;  numeric digits 20  /*insure there's enough decimal digits.*/
     a='67452301'x;  b="efcdab89"x;  c='98badcfe'x;  d="10325476"x;   x00='0'x;  x80="80"x
     #=length(!)                                 /*length in bytes of the input message.*/
     L=#*8//512;   if L<448  then plus=448 - L   /*is the length  less   than  448 ?    */
                   if L>448  then plus=960 - L   /* "  "     "   greater   "    "       */
                   if L=448  then plus=512       /* "  "     "    equal    to   "       */
                                                 /* [↓]  a little of this, ···          */
     $=! || x80 || copies(x00, plus%8 -1)reverse(right(d2c(8 * #), 4, x00)) || '00000000'x
                                                 /* [↑]       ···  and a little of that.*/
       do j=0  to length($) % 64 - 1             /*process the message  (lots of steps).*/
       a_=a;       b_=b;       c_=c;       d_=d  /*save the  original values  for later.*/
       chunk=j*64                                /*calculate the  size  of the chunks.  */
                       do k=1  for 16            /*process the message in chunks.       */
                       !.k=reverse( substr($, chunk + 1 + 4*(k-1), 4) )   /*magic stuff.*/
                       end   /*k*/                                        /*────step────*/
       a  =  .part1( a,   b,   c,   d,    0,    7,   3614090360)          /*■■■■  1 ■■■■*/
       d  =  .part1( d,   a,   b,   c,    1,   12,   3905402710)          /*■■■■  2 ■■■■*/
       c  =  .part1( c,   d,   a,   b,    2,   17,    606105819)          /*■■■■  3 ■■■■*/
       b  =  .part1( b,   c,   d,   a,    3,   22,   3250441966)          /*■■■■  4 ■■■■*/
       a  =  .part1( a,   b,   c,   d,    4,    7,   4118548399)          /*■■■■  5 ■■■■*/
       d  =  .part1( d,   a,   b,   c,    5,   12,   1200080426)          /*■■■■  6 ■■■■*/
       c  =  .part1( c,   d,   a,   b,    6,   17,   2821735955)          /*■■■■  7 ■■■■*/
       b  =  .part1( b,   c,   d,   a,    7,   22,   4249261313)          /*■■■■  8 ■■■■*/
       a  =  .part1( a,   b,   c,   d,    8,    7,   1770035416)          /*■■■■  9 ■■■■*/
       d  =  .part1( d,   a,   b,   c,    9,   12,   2336552879)          /*■■■■ 10 ■■■■*/
       c  =  .part1( c,   d,   a,   b,   10,   17,   4294925233)          /*■■■■ 11 ■■■■*/
       b  =  .part1( b,   c,   d,   a,   11,   22,   2304563134)          /*■■■■ 12 ■■■■*/
       a  =  .part1( a,   b,   c,   d,   12,    7,   1804603682)          /*■■■■ 13 ■■■■*/
       d  =  .part1( d,   a,   b,   c,   13,   12,   4254626195)          /*■■■■ 14 ■■■■*/
       c  =  .part1( c,   d,   a,   b,   14,   17,   2792965006)          /*■■■■ 15 ■■■■*/
       b  =  .part1( b,   c,   d,   a,   15,   22,   1236535329)          /*■■■■ 16 ■■■■*/
       a  =  .part2( a,   b,   c,   d,    1,    5,   4129170786)          /*■■■■ 17 ■■■■*/
       d  =  .part2( d,   a,   b,   c,    6,    9,   3225465664)          /*■■■■ 18 ■■■■*/
       c  =  .part2( c,   d,   a,   b,   11,   14,    643717713)          /*■■■■ 19 ■■■■*/
       b  =  .part2( b,   c,   d,   a,    0,   20,   3921069994)          /*■■■■ 20 ■■■■*/
       a  =  .part2( a,   b,   c,   d,    5,    5,   3593408605)          /*■■■■ 21 ■■■■*/
       d  =  .part2( d,   a,   b,   c,   10,    9,     38016083)          /*■■■■ 22 ■■■■*/
       c  =  .part2( c,   d,   a,   b,   15,   14,   3634488961)          /*■■■■ 23 ■■■■*/
       b  =  .part2( b,   c,   d,   a,    4,   20,   3889429448)          /*■■■■ 24 ■■■■*/
       a  =  .part2( a,   b,   c,   d,    9,    5,    568446438)          /*■■■■ 25 ■■■■*/
       d  =  .part2( d,   a,   b,   c,   14,    9,   3275163606)          /*■■■■ 26 ■■■■*/
       c  =  .part2( c,   d,   a,   b,    3,   14,   4107603335)          /*■■■■ 27 ■■■■*/
       b  =  .part2( b,   c,   d,   a,    8,   20,   1163531501)          /*■■■■ 28 ■■■■*/
       a  =  .part2( a,   b,   c,   d,   13,    5,   2850285829)          /*■■■■ 29 ■■■■*/
       d  =  .part2( d,   a,   b,   c,    2,    9,   4243563512)          /*■■■■ 30 ■■■■*/
       c  =  .part2( c,   d,   a,   b,    7,   14,   1735328473)          /*■■■■ 31 ■■■■*/
       b  =  .part2( b,   c,   d,   a,   12,   20,   2368359562)          /*■■■■ 32 ■■■■*/
       a  =  .part3( a,   b,   c,   d,    5,    4,   4294588738)          /*■■■■ 33 ■■■■*/
       d  =  .part3( d,   a,   b,   c,    8,   11,   2272392833)          /*■■■■ 34 ■■■■*/
       c  =  .part3( c,   d,   a,   b,   11,   16,   1839030562)          /*■■■■ 35 ■■■■*/
       b  =  .part3( b,   c,   d,   a,   14,   23,   4259657740)          /*■■■■ 36 ■■■■*/
       a  =  .part3( a,   b,   c,   d,    1,    4,   2763975236)          /*■■■■ 37 ■■■■*/
       d  =  .part3( d,   a,   b,   c,    4,   11,   1272893353)          /*■■■■ 38 ■■■■*/
       c  =  .part3( c,   d,   a,   b,    7,   16,   4139469664)          /*■■■■ 39 ■■■■*/
       b  =  .part3( b,   c,   d,   a,   10,   23,   3200236656)          /*■■■■ 40 ■■■■*/
       a  =  .part3( a,   b,   c,   d,   13,    4,    681279174)          /*■■■■ 41 ■■■■*/
       d  =  .part3( d,   a,   b,   c,    0,   11,   3936430074)          /*■■■■ 42 ■■■■*/
       c  =  .part3( c,   d,   a,   b,    3,   16,   3572445317)          /*■■■■ 43 ■■■■*/
       b  =  .part3( b,   c,   d,   a,    6,   23,     76029189)          /*■■■■ 44 ■■■■*/
       a  =  .part3( a,   b,   c,   d,    9,    4,   3654602809)          /*■■■■ 45 ■■■■*/
       d  =  .part3( d,   a,   b,   c,   12,   11,   3873151461)          /*■■■■ 46 ■■■■*/
       c  =  .part3( c,   d,   a,   b,   15,   16,    530742520)          /*■■■■ 47 ■■■■*/
       b  =  .part3( b,   c,   d,   a,    2,   23,   3299628645)          /*■■■■ 48 ■■■■*/
       a  =  .part4( a,   b,   c,   d,    0,    6,   4096336452)          /*■■■■ 49 ■■■■*/
       d  =  .part4( d,   a,   b,   c,    7,   10,   1126891415)          /*■■■■ 50 ■■■■*/
       c  =  .part4( c,   d,   a,   b,   14,   15,   2878612391)          /*■■■■ 51 ■■■■*/
       b  =  .part4( b,   c,   d,   a,    5,   21,   4237533241)          /*■■■■ 52 ■■■■*/
       a  =  .part4( a,   b,   c,   d,   12,    6,   1700485571)          /*■■■■ 53 ■■■■*/
       d  =  .part4( d,   a,   b,   c,    3,   10,   2399980690)          /*■■■■ 54 ■■■■*/
       c  =  .part4( c,   d,   a,   b,   10,   15,   4293915773)          /*■■■■ 55 ■■■■*/
       b  =  .part4( b,   c,   d,   a,    1,   21,   2240044497)          /*■■■■ 56 ■■■■*/
       a  =  .part4( a,   b,   c,   d,    8,    6,   1873313359)          /*■■■■ 57 ■■■■*/
       d  =  .part4( d,   a,   b,   c,   15,   10,   4264355552)          /*■■■■ 58 ■■■■*/
       c  =  .part4( c,   d,   a,   b,    6,   15,   2734768916)          /*■■■■ 59 ■■■■*/
       b  =  .part4( b,   c,   d,   a,   13,   21,   1309151649)          /*■■■■ 60 ■■■■*/
       a  =  .part4( a,   b,   c,   d,    4,    6,   4149444226)          /*■■■■ 61 ■■■■*/
       d  =  .part4( d,   a,   b,   c,   11,   10,   3174756917)          /*■■■■ 62 ■■■■*/
       c  =  .part4( c,   d,   a,   b,    2,   15,    718787259)          /*■■■■ 63 ■■■■*/
       b  =  .part4( b,   c,   d,   a,    9,   21,   3951481745)          /*■■■■ 64 ■■■■*/
       a  =  .a(a_, a);     b=.a(b_, b);      c=.a(c_, c);    d=.a(d_, d)
       end   /*j*/

     return c2x( reverse(a) )c2x( reverse(b) )c2x( reverse(c) )c2x( reverse(d) )
/*──────────────────────────────────────────────────────────────────────────────────────*/
.a:     return  right( d2c( c2d( arg(1) )   +   c2d( arg(2) ) ),  4, '0'x)
.h:     return  bitxor( bitxor( arg(1), arg(2) ), arg(3) )
.i:     return  bitxor( arg(2), bitor(arg(1), bitxor(arg(3),        'ffffffff'x)))
.f:     return  bitor( bitand(arg(1),arg(2)), bitand(bitxor(arg(1), 'ffffffff'x), arg(3)))
.g:     return  bitor( bitand(arg(1),arg(3)), bitand(arg(2), bitxor(arg(3), 'ffffffff'x)))
.Lr:    procedure;  parse arg _,#;           if #==0  then return _       /*left rotate.*/
                  ?=x2b(c2x(_));     return x2c( b2x( right(? || left(?, #), length(?) )))
.part1: procedure expose !.;   parse arg w,x,y,z,n,m,_;        n=n+1
                  return .a(.Lr(right(d2c(_+c2d(w) +c2d(.f(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part2: procedure expose !.;   parse arg w,x,y,z,n,m,_;        n=n+1
                  return .a(.Lr(right(d2c(_+c2d(w) +c2d(.g(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part3: procedure expose !.;   parse arg w,x,y,z,n,m,_;        n=n+1
                  return .a(.Lr(right(d2c(_+c2d(w) +c2d(.h(x,y,z))+c2d(!.n)),4,'0'x),m),x)
.part4: procedure expose !.;   parse arg w,x,y,z,n,m,_;        n=n+1
                  return .a(.Lr(right(d2c(c2d(w) +c2d(.i(x,y,z))+c2d(!.n)+_),4,'0'x),m),x)

output   when using the default (internal) inputs:

 in =
out = D41D8CD98F00B204E9800998ECF8427E

 in = a
out = 0CC175B9C0F1B6A831C399E269772661

 in = abc
out = 900150983CD24FB0D6963F7D28E17F72

 in = message digest
out = F96B697D7CB7938D525A2F31AAF161D0

 in = abcdefghijklmnopqrstuvwxyz
out = C3FCD3D76192E4007DFB496CCA67E13B

 in = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
out = D174AB98D277D9F5A5611C2C9F419D9F

 in = 12345678901234567890123456789012345678901234567890123456789012345678901234567890
out = 57EDF4A22BE3C955AC49DA2E2107B67A

Ring

See MD5("my string!") + nl
# output : a83a049fbe50cf7334caa86bf16a3520

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.

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

RPG

Modified from [3]:

**FREE
Ctl-opt MAIN(Main);
Ctl-opt DFTACTGRP(*NO) ACTGRP(*NEW);

dcl-pr QDCXLATE EXTPGM('QDCXLATE');
  dataLen         packed(5 : 0) CONST;
  data            char(32767) options(*VARSIZE);
  conversionTable char(10) CONST;
end-pr;

dcl-pr Qc3CalculateHash EXTPROC('Qc3CalculateHash');
  inputData             pointer value;
  inputDataLen          int(10) const;
  inputDataFormat       char(8) const;
  algorithmDscr         char(16) const;
  algorithmFormat       char(8) const;
  cryptoServiceProvider char(1) const;
  cryptoDeviceName      char(1) const options(*OMIT);
  hash                  char(64) options(*VARSIZE : *OMIT);
  errorCode             char(32767) options(*VARSIZE);
end-pr;

dcl-c HEX_CHARS CONST('0123456789ABCDEF');

dcl-proc Main;
  dcl-s inputData char(45);
  dcl-s inputDataLen int(10) INZ(0);
  dcl-s outputHash char(16);
  dcl-s outputHashHex char(32);
  dcl-ds algorithmDscr QUALIFIED;
    hashAlgorithm int(10) INZ(0);
  end-ds;
  dcl-ds ERRC0100_NULL QUALIFIED;
    bytesProvided int(10) INZ(0);  // Leave at zero
    bytesAvailable int(10);
  end-ds;
  
  dow inputDataLen = 0;
    DSPLY 'Input: ' '' inputData;
    inputData = %trim(inputData);
    inputDataLen = %len(%trim(inputData));
    DSPLY ('Input=' + inputData);
    DSPLY ('InputLen=' + %char(inputDataLen));
    if inputDataLen = 0;
      DSPLY 'Input must not be blank';
    endif;
  enddo;
  
  // Convert from EBCDIC to ASCII
  QDCXLATE(inputDataLen : inputData : 'QTCPASC');
  algorithmDscr.hashAlgorithm = 1;   // MD5
  // Calculate hash
  Qc3CalculateHash(%addr(inputData) : inputDataLen : 'DATA0100' : algorithmDscr
                   : 'ALGD0500' : '0' : *OMIT : outputHash : ERRC0100_NULL);
  // Convert to hex
  CVTHC(outputHashHex : outputHash : 32);
  DSPLY ('MD5: ' + outputHashHex);
  return;
end-proc;

// This procedure is actually a MI, but I couldn't get it to bind so I wrote my own version
dcl-proc CVTHC;
  dcl-pi *N;
    target char(65534) options(*VARSIZE);
    srcBits char(32767) options(*VARSIZE) CONST;
    targetLen int(10) value;
  end-pi;
  dcl-s i int(10);
  dcl-s lowNibble ind INZ(*OFF);
  dcl-s inputOffset int(10) INZ(1);
  dcl-ds dataStruct QUALIFIED;
    numField int(5) INZ(0);
    // IBM i is big-endian
    charField char(1) OVERLAY(numField : 2);
  end-ds;
  
  for i = 1 to targetLen;
    if lowNibble;
      dataStruct.charField = %BitAnd(%subst(srcBits : inputOffset : 1) : X'0F');
      inputOffset += 1;
    else;
      dataStruct.charField = %BitAnd(%subst(srcBits : inputOffset : 1) : X'F0');
      dataStruct.numField /= 16;
    endif;
    %subst(target : i : 1) = %subst(HEX_CHARS : dataStruct.numField + 1 : 1);
    lowNibble = NOT lowNibble;
  endfor;
  return;
end-proc;

Note that this implementation converts the input from EBCDIC to ASCII before computing the hash.

Sample output:

 DSPLY  Input:
 abcdefghijklmnopqrstuvwxyz
 DSPLY  Input=abcdefghijklmnopqrstuvwxyz
 DSPLY  InputLen=26
 DSPLY  MD5: C3FCD3D76192E4007DFB496CCA67E13B

Ruby

require 'digest'
Digest::MD5.hexdigest("The quick brown fox jumped over the lazy dog's back")
# => "e38ca1d920c4b8b8d3946b2c72f01680"

Rust

Cargo.toml

[dependencies]
rust-crypto = "0.2"

src/main.rs

extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;

fn main() {
    let mut sh = Md5::new();
    sh.input_str("The quick brown fox jumped over the lazy dog's back");
    println!("{}", sh.result_str());
}

S-lang

Support for MD5 and SHA-1 are included in the standard "chksum" library:

require("chksum");
print(md5sum("The quick brown fox jumped over the lazy dog's back"));
Output:
"e38ca1d920c4b8b8d3946b2c72f01680"

Scala

object RosettaMD5 extends App {

  def MD5(s: String): String = {
    // Besides "MD5", "SHA-256", and other hashes are available
    val m = java.security.MessageDigest.getInstance("MD5").digest(s.getBytes("UTF-8"))
    m.map("%02x".format(_)).mkString
  }

  assert("d41d8cd98f00b204e9800998ecf8427e" == MD5(""))
  assert("0cc175b9c0f1b6a831c399e269772661" == MD5("a"))
  assert("900150983cd24fb0d6963f7d28e17f72" == MD5("abc"))
  assert("f96b697d7cb7938d525a2f31aaf161d0" == MD5("message digest"))
  assert("c3fcd3d76192e4007dfb496cca67e13b" == MD5("abcdefghijklmnopqrstuvwxyz"))
  assert("e38ca1d920c4b8b8d3946b2c72f01680" == MD5("The quick brown fox jumped over the lazy dog's back"))
  assert("d174ab98d277d9f5a5611c2c9f419d9f" ==
    MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))
  assert("57edf4a22be3c955ac49da2e2107b67a" ==
    MD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890"))
  import scala.compat.Platform.currentTime
  println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
}

Seed7

$ include "seed7_05.s7i";
  include "msgdigest.s7i";

const proc: main is func
  begin
    writeln(hex(md5("The quick brown fox jumped over the lazy dog's back")));
  end func;
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Sidef

var digest = frequire('Digest::MD5');
say digest.md5_hex("The quick brown fox jumped over the lazy dog's back");

The same in OO manner

var md5 = require('Digest::MD5').new;
md5.add("The quick brown fox jumped over the lazy dog's back");
say md5.hexdigest;

Slate

You must load the code in 'src/lib/md5.slate'.

'The quick brown fox jumped over the lazy dog\'s back' md5String. "==> 'e38ca1d920c4b8b8d3946b2c72f01680'"


Slope

(display (string->md5 "The quick brown fox jumped over the lazy dog's back"))
Output:
e38ca1d920c4b8b8d3946b2c72f01680

Smalltalk

Using utility classes:

Works with: GNU Smalltalk
PackageLoader fileInPackage: 'Digest' !
(MD5 hexDigestOf: 'The quick brown fox jumped over the lazy dog''s back') displayNl.
Works with: Smalltalk/X
(MD5Stream hashValueOf: 'The quick brown fox jumped over the lazy dog''s back') printCR.

SQL

Works with: MySQL
SELECT MD5('The quick brown fox jumped over the lazy dog\'s back')

Suneido

Md5('The quick brown fox jumped over the lazy dog\'s back')

Tcl

Library: Tcllib (Package: md5)
package require md5
puts [md5::md5 -hex "The quick brown fox jumped over the lazy dog's back"]
# ==> E38CA1D920C4B8B8D3946B2C72F01680

UNIX Shell

Shells execute system commands (such as md5sum, in this case). We must pass "-n" to echo, so no trailing newline is appended, which would change the MD5-hash.

GNU coreutils has md5sum:

echo -n "The quick brown fox jumped over the lazy dog's back" | md5sum

Several BSD systems have md5:

echo -n "The quick brown fox jumped over the lazy dog's back" | md5
Library: OpenSSL
echo -n "The quick brown fox jumped over the lazy dog's back" |
  openssl md5 | sed 's/.*= //'

Visual Basic .NET

Works with: Visual Basic .NET version 9.0+
Imports System.Security.Cryptography
Imports System.Text

Module MD5hash
    Sub Main(args As String())
        Console.WriteLine(GetMD5("Visual Basic .Net"))
    End Sub

    Private Function GetMD5(plainText As String) As String
        Dim hash As String = ""

        Using hashObject As MD5 = MD5.Create()
            Dim ptBytes As Byte() = hashObject.ComputeHash(Encoding.UTF8.GetBytes(plainText))
            Dim hashBuilder As New StringBuilder

            For i As Integer = 0 To ptBytes.Length - 1
                hashBuilder.Append(ptBytes(i).ToString("X2"))
            Next
            hash = hashBuilder.ToString
        End Using

        Return hash
    End Function

End Module
Output:
AF397EA30996B22759740AC66452D47A

V (Vlang)

import crypto.md5
 
fn main() {
    for p in [
        // 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])
    }
}
 
fn validate(check string, s string) {
    sum := md5.hexhash(s)
    if sum != check {
        println("MD5 fail")
        println("  for string, $s")
        println("  expected:  $check")
        println("  got:       $sum")
    } else {
        println('MD5 succeeded $s')
    }
}
Output:
MD5 succeeded
MD5 succeeded a
MD5 succeeded abc
MD5 succeeded message digest
MD5 succeeded abcdefghijklmnopqrstuvwxyz
MD5 succeeded ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
MD5 succeeded 12345678901234567890123456789012345678901234567890123456789012345678901234567890
MD5 succeeded The quick brown fox jumped over the lazy dog's back

Wren

Library: Wren-crypto
Library: Wren-fmt

This script uses a library implementation of MD5 (based on the implementation in the MD5/Implementation#Wren task) to process the Wikipedia examples.

import "./crypto" for Md5
import "./fmt" for Fmt

var strings = [
    "The quick brown fox jumps over the lazy dog",
    "The quick brown fox jumps over the lazy dog.",
    ""
]

for (s in strings) {
    var digest = Md5.digest(s)
    Fmt.print("$s <== '$0s'", digest, s)
}
Output:
9e107d9d372bb6826bd81d3542a419d6 <== 'The quick brown fox jumps over the lazy dog'
e4d909c290d0fb1ca068ffaddf22cbd0 <== 'The quick brown fox jumps over the lazy dog.'
d41d8cd98f00b204e9800998ecf8427e <== ''

zkl

md5 is a built in utility

Utils.MD5.calc("message digest"); //-->"f96b697d7cb7938d525a2f31aaf161d0"
Utils.MD5.calc("abcdefghijklmnopqrstuvwxyz"); //-->"c3fcd3d76192e4007dfb496cca67e13b"

http://en.wikipedia.org/wiki/MD5

Cookies help us deliver our services. By using our services, you agree to our use of cookies.