Bonjour,

Je souhaite programmer un algorithme me retournant le md5 d'un texte.
Après de longues heures de travail je suis parvenu à obtenir un algorithme qui fonctionne mais je n'obtiens pas les mêmes empreintes qu'avec le md5 "officiel" (celui décrit par le RFC 1321).

J'obtiens actuellement 7A64D72B5402ED028CF9C8F2627D2B0A pour un message vide au lieu de d41d8cd98f00b204e9800998ecf8427e. Je pense donc que le problème viens des constantes.

Pour rappel le pseudo code du md5 est :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//Note: Toutes les variables sont sur 32 bits

//Définir r comme suit : 
var int[64] r, k
r[ 0..15] := {7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22}
r[16..31] := {5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20}
r[32..47] := {4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23}
r[48..63] := {6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21}

//MD5 utilise des sinus d'entiers pour ses constantes:
pour i de 0 à 63 faire
    k[i] := floor(abs(sin(i + 1)) × 2^32)
fin pour

//Préparation des variables:
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476

//Préparation du message (padding) :
ajouter "1" bit au message
ajouter "0" bits jusqu'à ce que la taille du message en bits soit égale à 448 (mod 512)
ajouter la taille du message codée en 64-bit little-endian au message

//Découpage en blocs de 512 bits:
pour chaque bloc de 512 bits du message
    subdiviser en 16 mots de 32 bits en little-endian w[i], 0 ≤ i ≤ 15

    //initialiser les valeurs de hachage:
    var int a := h0
    var int b := h1
    var int c := h2
    var int d := h3

    //pour principale:
    pour i de 0 à 63 faire
        si 0 ≤ i ≤ 15 alors
            f := (b et c) ou ((non b) et d)
            g := i
        sinon si 16 ≤ i ≤ 31 alors
                  f := (d et b) ou ((non d) et c)
                  g := (5×i + 1) mod 16
              sinon si 32 ≤ i ≤ 47 alors
                        f := b xor c xor d
                        g := (3×i + 5) mod 16
                    sinon si 48 ≤ i ≤ 63 alors
                              f := c xor (b ou (non d))
                              g := (7×i) mod 16
                          fin si
                    fin si
              fin si
        fin si

        var int temp := d
        d := c
        c := b
        b := ((a + f + k[i] + w[g]) leftrotate r[i]) + b
        a := temp
    fin pour

    //ajouter le résultat au bloc précédent:
    h0 := h0 + a
    h1 := h1 + b 
    h2 := h2 + c
    h3 := h3 + d
fin pour

var int empreinte := h0 concaténer h1 concaténer h2 concaténer h3 //(en little-endian)
Mon programme travaille en binaire et d'après ce que j'ai lu il faut coder le tout en little endian (bit le moins important en premier).

  • Première question : Certains sites donnent h0=0x01234567 comme première variable et ainsi de suite au lieu de ce qui est spécifié plus haut ... Si j'ai bien compris cela dépend de quels octets on met en premier. Quelle écriture dois-je utiliser ?
  • Deuxième question : Pour coder les variables hexadecimales je prends celles du pseudocode les convertit d'abord en binaire puis j'inverse le sens d'écriture pour obtenir du little-endian. Est-ce la bonne procédure ?
  • J'obtiens 10000000110001001010001011100110 pour h0 est-ce le bon résultat ?
  • De même j'obtiens 00011110001001010101011011101011 pour k[0] est-ce le bon résultat ?


PS: J'utilise caml comme language de programmation mais je ne pense pas que ça ait une importance pour ce problème.