Partage
  • Partager sur Facebook
  • Partager sur Twitter

Incompréhension par rapport au retour du hash md5

    23 avril 2019 à 18:23:30

    Bonjour,

    Je créé ce topic pour avoir un peu d'aide sur mon code C. Le script est lancé sous Windows et récupère un mot, une phrase ou un fichier que l'utilisateur transmet pour avoir un hash md5.

    J'ai le bon hash md5 lorsqu'il s'agit d'un mot ou d'une phrase comportant ou non des caractères spéciaux.

    Je l'ai aussi lorsque le fichier est un .txt, .c, .py; mais lorsque je veux avoir celui d'un fichier avec une en-tête (tout ce qui est pdf, jpeg, docx), le md5 n'est pas le bon.

    J'ouvre pourtant bien le fichier en binaire, je récupère bien les bons caractères lors de la lecture, j'ai fait un comparatif, pourtant le hash md5 est différent. Après 1 mois de recherche je ne trouves pas la solution, pouvez-vous me dire si le problème vient de la lecture du fichier ou des allocations mémoires?

    PS: le code ne fonctionne pas sous Linux, il y a un problème lors de l'exécution que je ne comprends pas non plus

    #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;
    }
    long nbcara=0;
    long inc = 0;
    
    int main( int argc, char *argv[] )
    {
        int j,k;
        char msg[1024];
        char *choix;
        char ad_fic[1024];
    
    
        printf("Si vous voulez avoir le hash d'un fichier, tapez 1.\n Pour un mot, tapez 2 : ");
        scanf("%s", choix);
    
        int c = atoi(choix);
    
        if (c == 1){
            FILE* fichier = NULL;
            printf("Entrez l'adresse du fichier.\n Comme nous sommes sous Windows, utiliser 2 \\ dans le chemin d'acces :\n");
            scanf("%s", ad_fic);
            fichier = fopen(ad_fic, "rb");  //on ouvre le fichier que l'on veut hacher
            char c;
    
            if (fichier != NULL){
                while((c = fgetc(fichier)) != EOF){
                    ++nbcara;							// on calcul le nombre de caractère pour créer le tableau qui va les récupérer
                }
                ++nbcara;
    
                rewind(fichier);
    
                char *message = (char *)malloc(nbcara);
    
                while ((c=fgetc(fichier)) != EOF){
    
                    message[inc] = c;				// on met dans le tableau tous les caractères pour pouvoir hacher
                    ++inc;
                }
                message[inc] = '\0';
    
                unsigned *d = md5(message, strlen(message));
                WBunion u;
    
                printf("Le hash md5 est : ");
                for (j=0;j<4; j++){
                    u.w = d[j];
                    for (k=0;k<4;k++) printf("%02x",u.b[k]);
                }
                printf("\n");
                free(message);
                system("PAUSE");
    
            }else{
                printf("Le fichier n'existe pas\n");
                system("PAUSE");
                return 0;
            }
    
        }else if (c == 2){
            printf("Entrez le mot a hacher : ");
    
            fgets(msg, 1024, stdin);
            scanf("%[^\n]", msg);
    
            unsigned *d = md5(msg, strlen(msg));
            WBunion u;
    
            printf("Le hash md5 est : ");
            for (j=0;j<4; j++){
                u.w = d[j];
                for (k=0;k<4;k++) printf("%02x",u.b[k]);
            }
            printf("\n");
            system("PAUSE");
    
        }else {
            printf("Erreur de commande\n");
            system("PAUSE");
            return 0;
        }
    
        return 0;
    }
    



    • Partager sur Facebook
    • Partager sur Twitter
      24 avril 2019 à 0:54:46

      Bonjour,

      Il y a un bug ligne 148, où le type de c devrait être int, et pas char.

      • Partager sur Facebook
      • Partager sur Twitter
        24 avril 2019 à 7:44:18

        Bonjour,

        En plus de l'erreur ligne 148, qui nous empêche de distinguer le caractère '@xFF' d'une fin de fichier.
        Il y en erreur ligne 167, qui considère que tout caractère '\0' est une fin de buffer.
        Ce code ne fonctionne pas pour tout fichier qui aurait au moins un octet valant 0x00 ou 0xFF.

        • Partager sur Facebook
        • Partager sur Twitter
        Bjarne Stroustrup : "C++ has become too expert friendly"
          25 avril 2019 à 17:33:56

          Bonjour,

          Merci pour vos retours.

          Concernant la ligne 148, ma variable c prend après comme valeur un caractère par caractère normalement (lignes 151 et 160), donc pourquoi il doit être un int plutôt qu'un char?

          Pour la ligne 167, comment je devrais faire pour qu'il prenne en compte les octets 0x00 ou 0xFF de mon fichier?  En python j'avais pourtant juste lu le fichier en binaire et l'envoyer dans la fonction de hachage et tout fonctionnait même avec les octets 0x00 et 0xFF, en quoi est-ce si différent du C qui ne veut pas?

          • Partager sur Facebook
          • Partager sur Twitter

          Incompréhension par rapport au retour du hash md5

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          • Editeur
          • Markdown