+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6
  1. #1
    Expert Confirmé Sénior

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : janvier 2006
    Messages : 3 656
    Points : 8 173
    Points
    8 173

    Par défaut [Article] La fonction MD5

    Il s'agit en fait d'une source avec une petite introduction pour le calcul du MD5 en C. Le ZIP contient tous les fichiers sources et exécutables (.exe), etc. présentés dans cette page.

    MD5 (Message-Digest version 5) est une fonction de hashage prenant en entrée un "message" de longueur quelconque et produisant en sortie une "signature numérique" (le message-digest) de 128 bits. Deux messages égaux ont le même MD5. La probabilité de trouver deux messages différents possédant le même MD5 en utilisant la technologie actuelle est extrêmement faible. Ainsi, ses principales applications sont le contrôle d'intégrité des données et le stockage de mot de passe dans les systèmes d'authentification. Il est décrit dans la RFC 1321. Nous-nous proposons d'écrire une fonction C permettant de calculer le MD5 d'un message. Il est évident que pour comprendre le code, il faut avoir lu la description de l'algorithme, sinon se contenter de l'utiliser

    Contraintes
    - MD5 utilise des entiers de taille fixée (32 bits, 64 bits, etc.), qui n'existent pas en C standard. Il faut donc en général passer par une série de #if et de typedef pour obtenir un type entier de taille connue d'avance pour n'importe quelle plateforme.
    - MD5 suppose que les données sont stockées en mémoire dans le format little-endian (les octets sont stockées en commençant par celui dont le poids est le plus faible). Il faut donc en général développer des macros permettant de mettre les octets dans le bon ordre.
    - Notre but étant de donner un exemple simple d'implémentation de MD5, nous avons volontairement choisi d'écrire du code spécifique à une plateforme de notre choix en utilisant un compilateur de notre choix :
    * Pour la plateforme cible, n'importe que système supportant nativement des entiers de 32 et 64 bits, utilisant 8 bits pour le type char et rangeant les données en mémoire selon le format little-endian. Nous choisissons le PC comme matériel et Windows, 32 ou 64 bits, comme logiciel.
    * Pour le compilateur : Microsoft Visual C++. L'implémentation du C de Microsoft supporte nativement les types __int32 (entier 32 bits) et __int64 (entier 64 bits). Ces types sont également supportés par Borland C++ et MinGW, pour ne citer qu'eux.
    * La fonction : elle permettra de calculer le MD5 d'un message dont la longueur est spécifiée en octets (même si MD5 accepte un message de n'importe quelle longueur, c'est-à-dire dont la longueur est spécifiée en bits).

    Préliminaires
    MD5 utilise un tableau de 64 entiers de 32 bits. Nous allons donc dans un premier temps créer un fichier que nous allons nommer t.data contenant ces 64 entiers. Tous les moyens sont bons, le plus simple étant de créer un programme qui va nous créer ce fichier.

    Fichier md5_tgen.c :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdio.h>
    #include <math.h>
     
    int main()
    {
        FILE * f = fopen("t.data", "wb");
     
        if (f == NULL)
            perror("t.data");
        else
        {
            __int32 i, t[64];
            __int64 Tm = 0x100000000;
     
            for(i = 0; i < 64; i++)
                t[i] = (__int32)(Tm * fabs(sin(i + 1)));
     
            fwrite(t, sizeof(t[0]), sizeof(t) / sizeof(t[0]), f);
     
            fclose(f);
        }
     
        return 0;
    }
    Codage
    Les fonctions que nous devons écrire :
    - md5_init() : charge le fichier t.data
    - md5() : calcule le MD5 d'un message fourni en argument
    - md5_format() : formate un MD5 afin qu'il soit lisible par un humain
    - d'autres qui nous viendront à l'esprit.

    Fichier md5.h :
    Code :
    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
    #ifndef H_MD5_MELEM_H
     
    #define H_MD5_MELEM_H
     
    /* Gestion des erreurs */
     
    #define MD5_SUCCEEDED(n) ((n) == 0)
     
    enum e_md5_errors {
        MD5_SUCCESS, MD5_INTERNAL_ERROR, MD5_INVALID_ARG, MD5_NO_MEM
    };
     
    /* Valeurs initiales des registres A, B, C et D */
     
    #define A0 0x67452301
    #define B0 0xefcdab89
    #define C0 0x98badcfe
    #define D0 0x10325476
     
    /* Definition des macros F, G, H et I */
     
    #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
    #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
    #define H(x, y, z) ((x) ^ (y) ^ (z))
    #define I(x, y, z) ((y) ^ ((x) | (~z)))
     
    /* Implementation de l'operateur <<< (rotate left) */
     
    #define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
     
    /* Definition des macros FXT, GXT, HXT et IXT et des constantes Snn */
     
    #define FXT(a, b, c, d, x, s, t) ((a) = (b) + ROL(((a) + F((b), (c), (d)) + (x) + (t)), (s)))
    #define GXT(a, b, c, d, x, s, t) ((a) = (b) + ROL(((a) + G((b), (c), (d)) + (x) + (t)), (s)))
    #define HXT(a, b, c, d, x, s, t) ((a) = (b) + ROL(((a) + H((b), (c), (d)) + (x) + (t)), (s)))
    #define IXT(a, b, c, d, x, s, t) ((a) = (b) + ROL(((a) + I((b), (c), (d)) + (x) + (t)), (s)))
     
    #define S11 7
    #define S12 12
    #define S13 17
    #define S14 22
    #define S21 5
    #define S22 9
    #define S23 14
    #define S24 20
    #define S31 4
    #define S32 11
    #define S33 16
    #define S34 23
    #define S41 6
    #define S42 10
    #define S43 15
    #define S44 21
     
    /* Declaration des fonctions */
     
    int  md5_init(void);
    int  md5(char * sum, const char * m, int bytes);
    void md5_format(char * output, const char * sum);
    void md5_format_ex(char * output, const char * buf, int bytes);
    int  md5_get_err_number(void);
    void md5_set_err_number(int n);
     
    #endif
    Fichier md5.c :
    Code :
    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
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    #include "md5.h"
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
     
    static int _md5_errno = MD5_SUCCESS;
    static unsigned T[64];
     
    static int md5_comput(char * sum, const char * buf, int bytes);
     
    int md5_init()
    {
        int ret = 0;
        FILE * f = fopen("t.data", "rb");
     
        if (f == NULL)
        {
            ret = -1;
            md5_set_err_number(MD5_INTERNAL_ERROR);
        }
        else
        {
            size_t n = fread(T, sizeof(T[0]), sizeof(T) / sizeof(T[0]), f);
     
            if (n != 64)
            {
                ret = -1;
                md5_set_err_number(MD5_INTERNAL_ERROR);
            }
     
            fclose(f);
        }
     
        return ret;
    }
     
    int md5(char * sum, const char * m, int bytes) /* Calcule le MD5 d'un message */
    {
        int ret = 0;
     
        /* Valider les arguments */
     
        if (sum == NULL || m == NULL || bytes < 0)
        {
            /* Arguments invalides */
     
            ret = -1;
            md5_set_err_number(MD5_INVALID_ARG);
        }
        else
        {
            /* Calculer la memoire necessaire pour la phase initiale */
     
            int N, mod, pad = 0;
            char * M;
     
            N = bytes + 1;
            mod = N % 64;
     
            if (mod != 56)
                pad = (N < 56) ? 56 - mod : 56 + 64 - mod;
     
            M = malloc(bytes + 1 + pad + 8);
     
            if (M == NULL)
            {
                /* Le systeme n'a pas assez de memoire */
     
                ret = -1;
                md5_set_err_number(MD5_NO_MEM);
            }
            else
            {
                /* Normaliser le message */
     
                __int64 n = bytes * 8; /* Longueur du message en bits */
                int N = bytes;
     
                memcpy(M, m, bytes);
     
                M[N] = '\x80'; /* Ajouter "10000000" */
                N++;
     
                if (pad != 0)
                {
                    memset(M + N, (unsigned char)0, pad); /* Completer par des "0" */
                    N += pad;
                }
     
                memcpy(M + bytes + 1 + pad, &n, sizeof(n)); /* Ajouter "n" */
                N += 8;
     
                /* Calculer le MD5 */
     
                ret = md5_comput(sum, M, N);
     
                free(M);
            }
        }
     
        return ret;
    }
     
    int md5_comput(char * sum, const char * buf, int bytes) /* Calcule le MD5 d'un message normalise */
    {
        int ret = 0;
        const unsigned * M = (const unsigned *)buf;
        int i, N = bytes / 4;
        unsigned r[4] = {A0, B0, C0, D0}; /* Registres A, B, C et D */
     
        for(i = 0; i < N / 16; i++)
        {
            const unsigned * x = (M + (16 * i));
            int j;
            unsigned s[4];
     
            for(j = 0; j < 4; j++)
                s[j] = r[j];
     
            j = 0;
     
            FXT(r[0], r[1], r[2], r[3], x[ 0], S11, T[j]); j++;
            FXT(r[3], r[0], r[1], r[2], x[ 1], S12, T[j]); j++;
            FXT(r[2], r[3], r[0], r[1], x[ 2], S13, T[j]); j++;
            FXT(r[1], r[2], r[3], r[0], x[ 3], S14, T[j]); j++;
            FXT(r[0], r[1], r[2], r[3], x[ 4], S11, T[j]); j++;
            FXT(r[3], r[0], r[1], r[2], x[ 5], S12, T[j]); j++;
            FXT(r[2], r[3], r[0], r[1], x[ 6], S13, T[j]); j++;
            FXT(r[1], r[2], r[3], r[0], x[ 7], S14, T[j]); j++;
            FXT(r[0], r[1], r[2], r[3], x[ 8], S11, T[j]); j++;
            FXT(r[3], r[0], r[1], r[2], x[ 9], S12, T[j]); j++;
            FXT(r[2], r[3], r[0], r[1], x[10], S13, T[j]); j++;
            FXT(r[1], r[2], r[3], r[0], x[11], S14, T[j]); j++;
            FXT(r[0], r[1], r[2], r[3], x[12], S11, T[j]); j++;
            FXT(r[3], r[0], r[1], r[2], x[13], S12, T[j]); j++;
            FXT(r[2], r[3], r[0], r[1], x[14], S13, T[j]); j++;
            FXT(r[1], r[2], r[3], r[0], x[15], S14, T[j]); j++;
     
            GXT(r[0], r[1], r[2], r[3], x[ 1], S21, T[j]); j++;
            GXT(r[3], r[0], r[1], r[2], x[ 6], S22, T[j]); j++;
            GXT(r[2], r[3], r[0], r[1], x[11], S23, T[j]); j++;
            GXT(r[1], r[2], r[3], r[0], x[ 0], S24, T[j]); j++;
            GXT(r[0], r[1], r[2], r[3], x[ 5], S21, T[j]); j++;
            GXT(r[3], r[0], r[1], r[2], x[10], S22, T[j]); j++;
            GXT(r[2], r[3], r[0], r[1], x[15], S23, T[j]); j++;
            GXT(r[1], r[2], r[3], r[0], x[ 4], S24, T[j]); j++;
            GXT(r[0], r[1], r[2], r[3], x[ 9], S21, T[j]); j++;
            GXT(r[3], r[0], r[1], r[2], x[14], S22, T[j]); j++;
            GXT(r[2], r[3], r[0], r[1], x[ 3], S23, T[j]); j++;
            GXT(r[1], r[2], r[3], r[0], x[ 8], S24, T[j]); j++;
            GXT(r[0], r[1], r[2], r[3], x[13], S21, T[j]); j++;
            GXT(r[3], r[0], r[1], r[2], x[ 2], S22, T[j]); j++;
            GXT(r[2], r[3], r[0], r[1], x[ 7], S23, T[j]); j++;
            GXT(r[1], r[2], r[3], r[0], x[12], S24, T[j]); j++;
     
            HXT(r[0], r[1], r[2], r[3], x[ 5], S31, T[j]); j++;
            HXT(r[3], r[0], r[1], r[2], x[ 8], S32, T[j]); j++;
            HXT(r[2], r[3], r[0], r[1], x[11], S33, T[j]); j++;
            HXT(r[1], r[2], r[3], r[0], x[14], S34, T[j]); j++;
            HXT(r[0], r[1], r[2], r[3], x[ 1], S31, T[j]); j++;
            HXT(r[3], r[0], r[1], r[2], x[ 4], S32, T[j]); j++;
            HXT(r[2], r[3], r[0], r[1], x[ 7], S33, T[j]); j++;
            HXT(r[1], r[2], r[3], r[0], x[10], S34, T[j]); j++;
            HXT(r[0], r[1], r[2], r[3], x[13], S31, T[j]); j++;
            HXT(r[3], r[0], r[1], r[2], x[ 0], S32, T[j]); j++;
            HXT(r[2], r[3], r[0], r[1], x[ 3], S33, T[j]); j++;
            HXT(r[1], r[2], r[3], r[0], x[ 6], S34, T[j]); j++;
            HXT(r[0], r[1], r[2], r[3], x[ 9], S31, T[j]); j++;
            HXT(r[3], r[0], r[1], r[2], x[12], S32, T[j]); j++;
            HXT(r[2], r[3], r[0], r[1], x[15], S33, T[j]); j++;
            HXT(r[1], r[2], r[3], r[0], x[ 2], S34, T[j]); j++;
     
            IXT(r[0], r[1], r[2], r[3], x[ 0], S41, T[j]); j++;
            IXT(r[3], r[0], r[1], r[2], x[ 7], S42, T[j]); j++;
            IXT(r[2], r[3], r[0], r[1], x[14], S43, T[j]); j++;
            IXT(r[1], r[2], r[3], r[0], x[ 5], S44, T[j]); j++;
            IXT(r[0], r[1], r[2], r[3], x[12], S41, T[j]); j++;
            IXT(r[3], r[0], r[1], r[2], x[ 3], S42, T[j]); j++;
            IXT(r[2], r[3], r[0], r[1], x[10], S43, T[j]); j++;
            IXT(r[1], r[2], r[3], r[0], x[ 1], S44, T[j]); j++;
            IXT(r[0], r[1], r[2], r[3], x[ 8], S41, T[j]); j++;
            IXT(r[3], r[0], r[1], r[2], x[15], S42, T[j]); j++;
            IXT(r[2], r[3], r[0], r[1], x[ 6], S43, T[j]); j++;
            IXT(r[1], r[2], r[3], r[0], x[13], S44, T[j]); j++;
            IXT(r[0], r[1], r[2], r[3], x[ 4], S41, T[j]); j++;
            IXT(r[3], r[0], r[1], r[2], x[11], S42, T[j]); j++;
            IXT(r[2], r[3], r[0], r[1], x[ 2], S43, T[j]); j++;
            IXT(r[1], r[2], r[3], r[0], x[ 9], S44, T[j]); j++;
     
            for(j = 0; j < 4; j++)
                r[j] += s[j];
        }
     
        memcpy(sum, r, 16);
     
        return ret;
    }
     
    void md5_format(char * output, const char * sum)
    {
        md5_format_ex(output, sum, 16);
    }
     
    void md5_format_ex(char * output, const char * m, int bytes)
    {
        int i;
     
        for(i = 0; i < bytes; i++)
        {
            sprintf(output, "%02x", (unsigned char)m[i]);
            output += 2;
        }
    }
     
    int md5_get_err_number()
    {
        return _md5_errno;
    }
     
    void md5_set_err_number(int n)
    {
        _md5_errno = n;
    }
    Exemple d'utilisation :
    Code :
    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
    #include <stdio.h>
    #include <string.h>
    #include "md5.h"
     
    int main()
    {
        printf("MD5 test suite :\n");
     
        if (!MD5_SUCCEEDED(md5_init()))
            fprintf(stderr, "La fonction md5_init a echoue avec le code d'erreur %d\n", md5_get_err_number());
        else
        {
            const char * t[] = {"", "a", "abc", "message digest"};
            char mdsum[16], mdoutput[32 + 1];
            size_t i;
     
            for(i = 0; i < sizeof(t) / sizeof(t[0]); i++)
            {
                printf("md5(\"%s\") = ", t[i]);
     
                if (!MD5_SUCCEEDED(md5(mdsum, t[i], (int)strlen(t[i]))))
                    printf("la fonction md5 a echoue avec le code d'erreur %d\n", md5_get_err_number());
                else
                {
                    md5_format(mdoutput, mdsum);
                    printf("%s\n", mdoutput);
                }
            }
        }
     
        return 0;
    }
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip MD5.zip (10,4 Ko, 132 affichages)

  2. #2
    Invité de passage
    Inscrit en
    février 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : février 2009
    Messages : 6
    Points : 1
    Points
    1

    Par défaut Parfait!

    Ce programme fonctionne parfaitement bien c'est exactement ce que je cherchais, le seul regret que je pourrais avoir c'est de ne pas êtres tombé dessus plus tôt.

    Merci

  3. #3
    Responsable Réseaux

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    mai 2007
    Messages
    11 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : mai 2007
    Messages : 11 282
    Points : 49 807
    Points
    49 807

    Par défaut

    Pour info, la RFC 1321 fournit un code directement compilable en C et fournit en plus un jeu minimal de tests permettant de tester l'implémentation.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    858
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 858
    Points : 1 153
    Points
    1 153

    Par défaut

    Salut,

    Nickel! A mon sens il faudrait étendre un petit peu à d'autres langages pour lesquels le MD5 et le stockage se justifient et font l'objet de librairies: Un snippet pour le python, un autre pour le PHP.

    A+

    Pfeuh

  5. #5
    CGi
    CGi est déconnecté
    Expert Confirmé Sénior
    Avatar de CGi
    Inscrit en
    mars 2002
    Messages
    951
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 951
    Points : 7 139
    Points
    7 139

    Par défaut

    Juste pour info, sous windows on peut le faire avec wincrypt
    un petit exemple :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
    #include <windows.h>
    #include <wincrypt.h>
    int main (void)
    {
        size_t i;
        unsigned char md5Hash[16];
        char *st = "Developpez";
        DWORD md5HashLen = 16;
        HCRYPTPROV hCryptProv;
        HCRYPTHASH hHash;
        if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) exit(1);
        if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) exit(1);
        CryptHashData(hHash, (BYTE*)st, strlen(st), 0);
        CryptGetHashParam(hHash, HP_HASHVAL, md5Hash, &md5HashLen, 0);
        if(hHash) CryptDestroyHash(hHash);
        if(hCryptProv) CryptReleaseContext(hCryptProv,0);
     
        for (i = 0; i < sizeof(md5Hash); i++) printf("%X", md5Hash[i]);
        return 0;
    }
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  6. #6
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    252
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 252
    Points : 54
    Points
    54

    Par défaut

    Bonsoir,

    Merci pour ce code.

    Est-il possible de se passer du fichier t.data?
    Pourquoi ne pas stocker les 64 entiers de 32 bits directement en mémoire vive?

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •