begin process at 2012 05 29 08:21:56
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C

 > 

Algorithme

 > 

Compression, Split & Cryptage

 > 

Erreur dans mon code SHA-1


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Erreur dans mon code SHA-1

mercredi 2 mars 2011 à 19:24:37 | Erreur dans mon code SHA-1

ndubien

Membre Club

Bonjour,

Je viens d'essayer de développer une application retournant la valeur hachée (SHA-1) d'un fichier, cependant malgré de nombreuses relectures du code et des documents disponibles sur internet relatifs à ce sujet, je ne parviens pas à trouver l'erreur.

Voici le code (il n'est pas optimisé, j'avais juste pour objectif de reprendre le c/c++ en créant un petit programme avec les connaissances qui me restaient à propos du langage):
Code C/C++ :
string SHA1( string nomFichier ) {

    /* Obtention des Mi (512 bits soit 64 octets) */
    /*
     - 1 est ajouté à la fin de x
     - On ajoute des 0 à la fin de x pour que ||x|| = 512n − 64
     - ||x|| est écrite en base 2 sur 64 bits, qui sont rajoutés à la fin du mot ci-dessus
    */

    ifstream monFlux;
    monFlux.open( nomFichier.c_str() );
    if( monFlux ) {
        monFlux.seekg (0, ios::end);
        unsigned int length = monFlux.tellg(); /* ATTENTION: au-delà de 2^32 :'( */
        monFlux.seekg (0, ios::beg);

        /* 512 bits = 64 octets */
        /*  64 bits =  8 octets */
        int nbLectures = ( length+1 +8 )/64;
        if( ( length+1 +8 )%64 > 0 ) ++nbLectures;

        unsigned int h0 = 0x67452301; /* unsigned int: 32 bits */
        unsigned int h1 = 0xEFCDAB89; /* http://www.commentcamarche.net/contents/cpp/cpptype.php3 */
        unsigned int h2 = 0x98BADCFE;
        unsigned int h3 = 0x10325476;
        unsigned int h4 = 0xC3D2E1F0;

        for( int i=0 ; i!=nbLectures ; ++i ) {

            int tailleLecture = 64; /* 64 octets */
            if( i == nbLectures-1 ) tailleLecture = length%64;

            char* buffer = new char[tailleLecture];
            monFlux.read( buffer, tailleLecture );

            unsigned int M[16]; /* 512 bits / 32 bits */
            for( int j=0 ; j!=16 ; ++j ) { M[j] = 0; }
            for( int t=0 ; t!=64 ; ++t ) {
                if( t < tailleLecture ) {
                    unsigned char tmp = *(buffer+t);
                    M[ t/4 ] += ( tmp << 8*( 3 - (t%4) ) );
                } else if( t == tailleLecture ) /* On ajoute le char: % 1000 0000 ie 128 */
                    M[ t/4 ] += ( 128 << 8*( 3 - (t%4) ) );
                /* length: "64" bits soit 2*32, on les ajoute après */
                /* else rien, on ajoute des 0 */
                if( i == nbLectures-1 ) {
                    /*M[ 14 ] = 0; length fait en réalité 32 bits */
                    M[15] = length;
                }
            }
            free( buffer );

            /* Obtient les Wt */
            unsigned int W[80];
            for( int t=0 ; t!=16 ; ++t ) { W[t] = M[t]; }
            for( int t=16 ; t!=80 ; ++t ) { W[t] = ROL32( W[t-3] xor W[t-8] xor W[t-14] xor W[t-16], 1 );  }

            /* A, B, C, D, E */
            unsigned int A = h0;
            unsigned int B = h1;
            unsigned int C = h2;
            unsigned int D = h3;
            unsigned int E = h4;

            /* Boucle sur t... */
            for( int t=0 ; t!=80 ; ++t ) {
                /*
                T = S5(A) + (ft(B,C,D) + Kt) + E + Wt
                E = D
                D = C
                C = S30(B)
                B = A
                A = T
                */
                unsigned int tmp;
                /* 19/ (B &#8743; C) or (¬B &#8743; D) *//* 39/ B xor C xor D *//* 59/ (B &#8743; C) or (B &#8743; D) or (C &#8743; D) *//* B xor C xor D */
                if( t <= 19 )      tmp = ( (B & C) | ((~B) & D) )        + 0x5A827999;
                else if( t <= 39 ) tmp = ( B ^ C ^ D )                   + 0x6ED9EBA1;
                else if( t <= 59 ) tmp = ( (B & C) | (B & D) | (C & D) ) + 0x8F1BBCDC;
                else               tmp = ( B ^ C ^ D )                   + 0xCA62C1D6;

                unsigned int T = ROL32(A,5) + tmp + E + W[t];
                E = D;
                D = C;
                C = ROL32(B,30);
                B = A;
                A = T;
            }

            /* Ajouter A à H0, B à H1, C à H2, D à H3 et E à H4 */
            h0 += A;
            h1 += B;
            h2 += C;
            h3 += D;
            h4 += E;
        }

        monFlux.close();

        return hexa_of_valeurhachee( (unsigned int[]){h0,h1,h2,h3,h4} );
    } else return 0;
}


Le problème est qu'elle ne renvoie pas la bonne valeur hachée:
* Pour le fichier "test":
retour = 9b0decbd3c093f369d6d2462d784ad49a9ff4698
au lieu de = a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
* Pour le fichier "": le retour est correct da39a3ee5e6b4b0d3255bfef95601890afd80709

Merci d'avance et à bientôt...

Nico
PS: Articles concernant le hachage SHA-1:
http://en.wikipedia.org/wiki/SHA-1
http://fr.wikipedia.org/wiki/Sp%C3%A9cifications_SHA-1
http://www.sinfocol.org/herramientas/hashes.php
mercredi 2 mars 2011 à 22:39:02 | Re : Erreur dans mon code SHA-1

Lucky92

Salut,

Je ne suis pas sûr de mon coup car j'ai survolé très vite ton problème et je n'ai pas eu le temps de tester, mais dans l'article wikipédia que tu cites, il est dit que les constantes sont fournies en big endian. Or, si tu utilises un PC, il y a forte chance que tu sois en little endian ; tu peux essayer de permuter les octets des constantes hexa.

@+.
mercredi 2 mars 2011 à 23:47:56 | Re : Erreur dans mon code SHA-1

ndubien

Membre Club
Bonjour,

Le projet a en effet été compilé sous Windows (avec CodeBlocks), mais je souhaitais également pouvoir le recompiler sous Linux (Ubuntu avec CodeBlocks (gcc)).

Comment faut-il procéder pour passer de big endian à little endian ?
Pourrais-je conserver le même code pour Linux ou faudra-t'il changer ceci d'une version à l'autre ?

Merci d'avance et à bientôt...
Nico
jeudi 3 mars 2011 à 06:59:42 | Re : Erreur dans mon code SHA-1

Lucky92

Salut,

L'endianness ne dépend ni de l'OS ni du compilateur mais de l'architecture matérielle. Elle correspond à la représentation des données en mémoire, et dans le monde PC, les données sont représentées en little endian.
Il suffit de permuter les octets dans les constantes comme ceci :

Code C/C++ :
 unsigned int h0 = 0x01234567; //0x67452301; 
 unsigned int h1 = 0x89ABCDEF; //0xEFCDAB89; 
 unsigned int h2 = 0xFEDCBA98; //0x98BADCFE;
 unsigned int h3 = 0x76543210; //0x10325476;
 unsigned int h4 = 0xF0E1D2C3; //0xC3D2E1F0;


 if( t <= 19 )      tmp = ( (B & C) | ((~B) & D) )        + 0x9979825A; //+ 0x5A827999;
 else if( t <= 39 ) tmp = ( B ^ C ^ D )                   + 0xA1EBD96E; //+ 0x6ED9EBA1;
 else if( t <= 59 ) tmp = ( (B & C) | (B & D) | (C & D) ) + 0xDCBC1B8F; //+ 0x8F1BBCDC;
 else               tmp = ( B ^ C ^ D )                   + 0xD6C162CA; //+ 0xCA62C1D6;


@+
jeudi 3 mars 2011 à 11:13:33 | Re : Erreur dans mon code SHA-1

ndubien

Membre Club

Bonjour,

Je viens d'essayer les modifications que vous m'avez suggéré, cependant le problème persiste, je n'obtiens toujours pas le bon résultat.

Merci d'avance et à bientôt... Nico
jeudi 3 mars 2011 à 12:55:54 | Re : Erreur dans mon code SHA-1

Lucky92

Peux-tu poster la macro ROL32 ?
jeudi 3 mars 2011 à 13:06:34 | Re : Erreur dans mon code SHA-1

Lucky92

..et l'opérateur ou la macro xor aussi.
jeudi 3 mars 2011 à 13:09:13 | Re : Erreur dans mon code SHA-1

Lucky92

...et la fonction hexa_of_valeurhachee aussi.
jeudi 3 mars 2011 à 16:05:00 | Re : Erreur dans mon code SHA-1

ndubien

Membre Club

Bonjour,

Voici les fonctions que vous m'avez demandé:
Code C/C++ :
string hexa_of_uint( unsigned int entier ) {
    string hexa = "";
    for( int i=0 ; i!=8 ; ++i ) { /* entier: 32 bits, hexa: 4bits */
        switch( entier%16 ) {
            case 0:  hexa = "0" + hexa; break;
            case 1:  hexa = "1" + hexa; break;
            case 2:  hexa = "2" + hexa; break;
            case 3:  hexa = "3" + hexa; break;
            case 4:  hexa = "4" + hexa; break;
            case 5:  hexa = "5" + hexa; break;
            case 6:  hexa = "6" + hexa; break;
            case 7:  hexa = "7" + hexa; break;
            case 8:  hexa = "8" + hexa; break;
            case 9:  hexa = "9" + hexa; break;
            case 10: hexa = "a" + hexa; break;
            case 11: hexa = "b" + hexa; break;
            case 12: hexa = "c" + hexa; break;
            case 13: hexa = "d" + hexa; break;
            case 14: hexa = "e" + hexa; break;
            case 15: hexa = "f" + hexa; break;
            default: hexa = "*" + hexa; break;
        }
        entier /= 16;
    }
    return hexa;
}

string hexa_of_valeurhachee( unsigned int* valeurhacheee ) {
    string hexa = "";
    for( int i=0 ; i!= 5 ; ++i ) { hexa += hexa_of_uint( *(valeurhacheee+i) ); }
    return hexa;
}

et ROL32:
Code C/C++ :
#define ROL32(x,b) (((x) << (b)) | ((x) >> (32 - (b))))


pour les fonctions xor, or et and j'utilise les fonctions de bases définies par le langage (xor:uint*uint->uint...).

Merci d'avance et à bientôt...
Nico
jeudi 3 mars 2011 à 19:32:45 | Re : Erreur dans mon code SHA-1

Lucky92

Réponse acceptée !
Bingo !

Remplace simplement :
Code C/C++ :
 M[15] = length;


Par :
Code C/C++ :
 M[15] = length * 8;


Dans l'algo la taille à hacher est exprimée en nombre de bits et non en nombre de bytes.

good bytes:)

PS : au temps pour moi pour la fausse piste de l'endianness.

1 2

Cette discussion est classée dans : int, bits, unsigned, if, monflux


Répondre à ce message

Sujets en rapport avec ce message

Hexadécimal HELP ! [ par Xentor ] Bonjour,Mon problème est le suivant : je vient d'effectuer un AND sur une variable, et celle ci, bien que conservant son type unsigned int se met en h conversion constante en hexa ->unsigned long ou int ??? [ par andrealphus ] 4ndr&@lphu$rebonjour à tous et toutes,mon nouveau probleme est ridicule mais gênant...comment peut on convertir un nombre hexadécimal (du style l'adre Fch. Header :: CONIO.H [ par TontOnDuWeb ] Pour ce que ca interesse (avec vc++ les fonctions suivantes e sont pas incluse (du moins je crois...))>>#if !defined(__CONIO_H)#define __CONIO_H#if !d pb de retour( du tableau) de ma fonction [ par airwann ] bonjour,j ai un problème comment dois je modifier l'entête de ma fonction pour recupérer le tableau de structure 3 d alloué dynamiquementmerci d avanc transformer un tableau 2d en image bitmap [ par gyzmo1 ] Bonjour a tous, voilà mon problème, je suis en train de mettre en place une méthode de comparaison de signature manuscrites. Cette méthode s applique Segmentation Fault....en traitement d'image [ par psysta ] Bonjour,je suis nouveau dans la programmation en C. J'ai un programme Matlab qui marche bien, et je souhaiterais l'implémenter en C. Le pgm compile bi PB DIALOGBOX (Win32) [ par moustachu ] Bonjour,Je dois recréer des projets VC++6.0 à partir des fichiers dont je dispose. Le problème se pose avec un fichier chgmod.rc. J'arrive bien à l'ou class matrice [ par flaky ] Slt à tousJ'utilise une classe "matrice" (celle de nicolas aunai, téléchargée sur le site) qui fonctionne très bien. Mais j'ai du mal à manipuler l'ob Pointeurs et Desallocation [ par gilimcce ] Bonjour à tous....je declare une fonctionloadJpegImage(char *, unsigned char*, int*, int*)1e parametre : le chemin de l'image chargee2e //


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,858 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales