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.




 
/* 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"
 