IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Chiffrage de fichier avec XOR


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut Chiffrage de fichier avec XOR (et clé md5)
    Bonjour à tous,

    J'essaie de chiffrer un fichier à l'aide d'une clé et de l'opération xor sur tout le fichier. Bien entendu la clé est plus petite que le fichier à chiffrer du coup la clé est parcourue en boucle.

    Cependant j'ai un petit problème au niveau du déchiffrage, le programme se lance mais quitte directement sans rien faire. On dirait qu'il plante et il y a une erreur mémoire (instruction xxx ... impossible de read)

    J'ai peut-être commis une erreur dans le chiffrage puisque je suis totalement novice en chiffrage et en C++ en plus. D'après ce que j'ai compris je peux utiliser la même opération que le chiffrage, au niveau du xor, pour déchiffrer, est-ce exacte ?

    Sinon voici mon code :

    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
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
     
    using namespace std;
     
    void crypt(const char *text, const char *key, char *crypted) {
         unsigned int j = 0;
         for (unsigned int i = 0; i<strlen(text); i++) {
             if (j >= strlen(key)) {
                   j=0;
             }
             crypted[i] = text[i]^key[j];
             j++;
         }
    }
     
    int main(int argc, char *argv[])
    {
        char *key = "9cdfb439c7876e703e307864c9167a15";
        fstream file_in("text.txt", ios::in|ios::binary);
        fstream file_out("text-out.txt", ios::out|ios::binary);
        int iter = 0;
        const int tranche = 192;
        char buffer[tranche];
        while (!file_in.eof()) {
              file_in.getline(buffer, (iter*tranche)+tranche);
              char tmp[tranche];
              crypt(buffer, key, tmp);
              strcpy(buffer, tmp);
              file_out.write(buffer, strlen(buffer));
              iter++;
        }
        file_in.close();
        file_out.close();
     
        cout << "\nFini\n";
        system("PAUSE");
        return 0;
    }
    Ce serait pour après mais peut-être aussi pouvez-vous m'aider pour que la clé key soit interpretée comme du hex car pour le moment c'est du char.
    J'ai sûrement fait des erreurs bêtes et coder comme un pied mais j'espère que vous saurez me mettre sur le bon chemin !

    Merci d'avance.

  2. #2
    Membre éprouvé Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Par défaut
    Cette ligne pose problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    file_in.getline(buffer, (iter*tranche)+tranche);
    Puisque "getline" attends comme second paramètre la taille du buffer, or ton buffer est de taille "tranche" et non pas de taille (iter*tranche)+tranche.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Ah oui ça change tout, par contre j'ai toujours un gros problème avec les fichiers. Je n'obtient pas les mêmes fichiers à l'arrivée.

    Voici le bout de code simplifié :

    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
    int main(int argc, char *argv[])
    {
        char *key = "9cdfb439c7876e703e307864c9167a15";
        char *filename_in = "image-tocrypt.jpg";
        char *filename_out = "image-out.jpg";
        fstream file_in(filename_in, ios::in|ios::binary);
        fstream file_out(filename_out, ios::out|ios::binary);
     
        if (!file_in || !file_out) {
              cout << "Impossible d'ouvrir !";
              return 0;
        }
     
        int iter = 0;
        const int tranche = 192;
        char buffer[tranche];
     
        // Determine la longueur du fichier
        file_in.seekg(0, ios::end);
        int file_inlength = file_in.tellg();
        file_in.seekg(0, ios::beg);
     
        while (iter*tranche < file_inlength) {
              file_in.read(buffer, tranche);
              //char tmp[tranche];
              //crypt(buffer, key, tmp);
              //strcpy(buffer, tmp);
              file_out.write(buffer, tranche);
              iter++;
        }
        file_in.close();
        file_out.close();
     
        cout << "\nFini\n";
        system("PAUSE");
        return 0;
    }
    J'ai testé avec une photo et si j'utilise getline c'est illisible alors qu'avec read c'est presque parfait. J'arrive à voir la photo mais il y a quelques octets en trop, 124 pour être précis. Poids avant: 33'860 o ; après : 33'984 o. Sûrement une erreur dans la boucle mais laquelle ?

  4. #4
    Membre éprouvé Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Par défaut
    Le problème c'est que getline s'utilise principalement avec des fichiers texte, or avec des fichiers binaire, cela n'a pas de sens. Je te conseille d'utiliser read au lieu de getline. Notamment, getline va ignorer tous les '\n' qui peuvent tout à fait apparaître aléatoirement dans un fichier binaire.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    En effet je viens de l'apprendre à mes dépends. Je viens de corriger la copie est conforme (les deux MD5 concordent).

    Maintenant il y a un problème avec le chiffrage. En effet j'ai remarqué que tout à l'air juste, j'ai vérifié par-ci par là c'est juste sauf le dernier byte où le xor semble être faux.

    J'ai essayé de faire le déchiffrage mais c'est totalement faux, je retrouve à peine 50% des données. J'ai regardé en HEX et je voyais à peu près la moitié qui revenait par rapport au fichier original.

    Je suis persuadé que vous pouvez m'aider, voici mon code actuellement :

    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
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
     
    using namespace std;
     
    void crypt(const char *text, const int length, const char *key, char *crypted) {
         int j = 0;
         for (int i = 0; i<length; i++) {
             if (j >= (signed) strlen(key)) {
                   j=0;
             }
             crypted[i] = text[i]^key[j];
             j++;
         }
    }
     
    int main(int argc, char *argv[])
    {
        char *key = "9cdfb439c7876e703e307864c9167a15";
        char *filename_in = "image-tocrypt.jpg";
        char *filename_out = "image-out.jpg";
        fstream file_in(filename_in, ios::in|ios::binary);
        fstream file_out(filename_out, ios::out|ios::binary);
     
        if (!file_in || !file_out) {
              cout << "Impossible d'ouvrir !";
              return 0;
        }
     
        int iter = 0;
        const int tranche = 192;
        char buffer[tranche];
     
        // Determine la longueur du fichier
        file_in.seekg(0, ios::end);
        int file_inlength = file_in.tellg();
        file_in.seekg(0, ios::beg);
     
        while (iter*tranche < file_inlength) {
              int readByte;
              readByte = tranche;
              if (iter*tranche+tranche > file_inlength)
                 readByte = file_inlength-iter*tranche;
              strcpy(buffer, "");
              file_in.read(buffer, readByte);
              char tmp[tranche];
              crypt(buffer, readByte, key, tmp);
              strcpy(buffer, tmp);
              file_out.write(buffer, readByte);
              iter++;
        }
        file_in.close();
        file_out.close();
     
        cout << "\nFini\n";
        system("PAUSE");
        return 0;
    }
    Merci d'avance !

    PS: Apparement le chiffrage est faux, une partie des données est chiffrée mais pas tout. J'ai fais passé un fichier texte et on voit clairement des données, y'a quelque chose qui cloche ! (Normal du coup que le déchiffrage ne fonctionne pas).

  6. #6
    Membre émérite Avatar de 10_GOTO_10
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    890
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 890
    Par défaut
    J'espère que ce que tu as à chiffrer n'est pas important. Le cryptage avec un XOR utilisé plus d'une fois, c'est à peu près équivalent à donner le fichier en clair (alors que, paradoxalement, utilisé une seule fois, il est prouvé que c'est absolument indéchiffrable ...).

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Citation Envoyé par 10_GOTO_10 Voir le message
    J'espère que ce que tu as à chiffrer n'est pas important. Le cryptage avec un XOR utilisé plus d'une fois, c'est à peu près équivalent à donner le fichier en clair (alors que, paradoxalement, utilisé une seule fois, il est prouvé que c'est absolument indéchiffrable ...).
    Pour le moment je fais des tests sur des fichiers totalement inutile. Par contre tu as mal compris ce que je voulais dire. Mon code actuellement ne chiffre pas correctement, on dirait qu'il chiffre partiellement et je parle bien de chiffrer la première fois donc 1 seul fois l'opération crypt() ! J'ai constaté ceci car le fichier, une fois passé dans crypt() a des parties (mots voire phrases) totalement non-chiffrées, donc lisibles !

  8. #8
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Citation Envoyé par 10_GOTO_10 Voir le message
    J'espère que ce que tu as à chiffrer n'est pas important. Le cryptage avec un XOR utilisé plus d'une fois, c'est à peu près équivalent à donner le fichier en clair (alors que, paradoxalement, utilisé une seule fois, il est prouvé que c'est absolument indéchiffrable ...).
    Il est indéchiffrable seulement si la longueur de clé (tirer au hasard) est aussi longue que la phrase à crypter.

  9. #9
    Membre éprouvé Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Par défaut
    Je ne sais pas si c'est lié mais le fait est que ta clé est extrêmmement pauvre: elle n'utilise que les caractère 0-9 et a-f c'est à dire seulement 16 sur 256 possibles et qui ont la facheuse tendance d'avoir beaucoup de bits en commun. Si tu veux une clée en hexadécimal il ne faut pas t'y prendre comme cela. Sinon je ne vois pas d'autre erreurs mais cela ne veut pas dire qu'il n'y en a pas.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Voilà j'ai bien avancé ! J'ai enfin réussi à trouver pourquoi mon code ne semblait pas chiffrer tout mon fichier. Ta thérorie amaury pouly n'est pas juste, le coupable se trouvait dans l'instruction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    strcpy(buffer, tmp);
    file_out.write(buffer, readByte);
    Pourquoi ? Je ne sais pas mais on dirait que certains octets restait dans le buffer à la lecture et que strcpy n'écrasait pas l'ancien buffer par les octets chiffrés, du coup il devait rester des parties du fichier venant directement de la lecture et donc en clair !

    Pour répondre à Goten, je compte utiliser une clé assez courte car une clé de la longueur du fichier est peu pratique et que je n'ai pas besoin d'un chiffrage si avancé. Malgré qu'il soit "pauvre", ça me suffira je pense. Donc je voulais dire que je parcoure la clé autant de fois qu'il le faut pour chiffrer l'intégralité du fichier (ça revient à dire que la clé est de la taille du fichier mais totalement redondant, donc faillible c'est vrai). Pour améliorer cela je pourrais prendre une clé SHA512 ou plus par exemple.

    Voici mon code actuelle :


    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
    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
    #include <cstdlib>
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <math.h>
     
    using namespace std;
     
    // Chiffrage
    // -- selon une clé char
    void crypt(char *text, int length, char *key, char *crypted) {
         int j = 0;
         for (int i = 0; i < length; i++) {
             if (j%strlen(key) == 0) {
                   j=0;
             }
             crypted[i] = text[i] ^ key[j];
             j++;
         }
    }
     
    // -- selon une clé en binary
    void crypt(char *text, int length, double key, char *crypted) {
         int j = 0;
         char keychar[25];
         sprintf(keychar, "%15.0f", key);
         cout << "! " << keychar << endl;
         for (int i = 0; i < length; i++) {
             if (i%strlen(keychar) == 0) {
                   j=0;
             }
             crypted[i] = text[i] ^ keychar[j];
             j++;
         }
    }
     
    double convert_key_binary(char *key) {
         double result;
         result = 0;
         for (unsigned int i = 0; i < strlen(key); i++) {
             int tmp;
             char car = key[ ((strlen(key)-1)-i) ];
             switch ( car ) {
                    case '0': tmp = 0; break;
                    case '1': tmp = 1; break;
                    case '2': tmp = 2; break;
                    case '3': tmp = 3; break;
                    case '4': tmp = 4; break;
                    case '5': tmp = 5; break;
                    case '6': tmp = 6; break;
                    case '7': tmp = 7; break;
                    case '8': tmp = 8; break;
                    case '9': tmp = 9; break;
                    case 'a': tmp = 10; break;
                    case 'b': tmp = 11; break;
                    case 'c': tmp = 12; break;
                    case 'd': tmp = 13; break;
                    case 'e': tmp = 14; break;
                    case 'f': tmp = 15; break;
                    default : cout << "Error"; return 0;
             }
             result += tmp*( pow(16, ((strlen(key)-1)-i)) );
         }
         return result;
    }
     
    int main(int argc, char *argv[])
    {
        char *key = "9cdfb439c7876e703e307864c9167a15";
        double keyhex = convert_key_binary(key);
        printf("%f\n", keyhex);
        char *filename_in = "text.txt";
        char *filename_out = "text-out.txt";
        fstream file_in(filename_in, ios::in|ios::binary);
        fstream file_out(filename_out, ios::out|ios::binary);
     
        if (!file_in || !file_out) {
              cout << "Impossible d'ouvrir !";
              return 0;
        }
     
        int iter = 0;
        const int tranche = 192;
        char buffer[tranche];
     
        // Determine la longueur du fichier
        file_in.seekg(0, ios::end);
        int file_inlength = file_in.tellg();
        file_in.seekg(0, ios::beg);
     
        while (iter*tranche < file_inlength) {
              int readByte;
              readByte = tranche;
              if (iter*tranche+tranche > file_inlength)
                 readByte = file_inlength-iter*tranche;
              strcpy(buffer, "");
              file_in.read(buffer, readByte);
              char tmp[readByte];
              crypt(buffer, readByte, key, tmp);
              /*strcpy(buffer, tmp); <-- Si je décommente, 
                               certaines parties du fichier 
                               reste visibles après le chiffrage !!! */
              file_out.write(tmp, readByte);
              iter++;
        }
        file_in.close();
        file_out.close();
     
        cout << "\nFini\n";
        system("PAUSE");
        return 0;
    }
    Comme vous pouvez le voir il s'est agrandit, j'ai rajouté une fonction surchargée pour prendre en charge la clé en binaire à proprement dit. Je veux dire par là que ma clé key est en fait un checksum d'un mot de passe. C'est à dire que normalement ce checksum est en binaire à l'origine et que pour des raisons de facilités il est plus facile de l'exprimer en hex, c'est plus facile à transférer.

    J'ai donc un mot de passe xxx qui passe dans un MD5 et donne en hex "9cdfb439c7876e703e307864c9167a15". Ici C++ le reconnait comme une chaine et c'est dans le but de le convertir dans son format d'origine (en bytes) que j'ai créer la deuxième fonction crypt.
    Je commence par convertir key en decimal (base 16 > 10) ça fait un énorme nombre de l'ordre de 10e+38 (16^31), j'utilise ma fonction convert_key_binary pour se faire. Ensuite j'envoie ce `double` à la fonction crypt qui convertit celui-ci en char pour pouvoir le parcourir octet par octet.

    D'après moi ma conversion est totalement fausse car j'obtient un chiffre avec pleins de zéros (108536561009105580000000000000000000000). L'ordre de grandeur est gardé mais où sont tout mes chiffres !? (Pour info, c'est l'instructions printf au début de mon main qui affiche ce nombre.)

    Est-ce que ma méthode pour convertir l'hex en décimal est juste ?
    Est-ce qu'il y aurait une autre méthode pour appliquer xor à ma clé mais en la convertissant en binaire avant ?

    Un petit coup de pouce pour la convertion ne serait pas de refus. Merci d'avance.

  11. #11
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Même si un double peut contenir ton énorme nombre, il ne peut pas garder tous les chiffres (un double c'est comme un float, mais avec deux fois plus de chiffres "significatifs", si on peut dire).
    Si tu veux quelque chose de précis, il faut absolument travailler sur des entiers (et je pense que tu devra te servir d'une bibliothèque spécialisée, car je ne pense pas qu'un nombre de l'ordre de 10^31 puisse être géré par les types standards).

  12. #12
    Membre éprouvé Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Par défaut
    Je viens de comprendre pourquoi, le strcpy m'avait échappé ! En effet, strcpy copie une chaîne de caractère dans une autre, or tu ne manipules pas de chaînes de caractères !
    Autrement dit, ton strcpy peut potentiellement faire n'importe quoi, c'est à dire écrire moins que readBytes(c'est ton cas visiblement) ou plus(et faire un buffer overflow et tout ce qui suit...).

    Concernant le double c'est assez horrible d'utiliser un tel code étant donné que si tu ne fais pas attention, le résultat peut être non déterministe(!). De plus, ton immense code(9cdfb439c7876e703e307864c9167a15) ne peut pas tenir dans un double:
    9cdfb439c7876e703e307864c9167a15 -> 2,08521104953385306819e38
    Or log(2,08521104953385306819e38)/log(2) -> 127
    Donc pour stocker ton nombre il faut 128 bit, or un double n'en fait que 64...
    Je te conseille donc soit de réduire ta clef et de la stocker dans un entier(long), soit de la garder dans une chaîne de caractère.

  13. #13
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Aussi, n'oubliez pas qu'un \0 stoppe une chaîne, donc un cryptage XOR pur n'est pas adapté aux chaînes de caractères (le résultat peut être une chaîne tronquée).

    Pour corriger cela, deux options: Soit traiter les données comme un tableau d'octets (donc, plus de strlen() ou strcpy() nulle part), soit mettre une petite exception dans le xor:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if(text[i] == key[i])
    	crypted[i] = text[i];
    else
    	crypted[i] = text[i] ^ key[i];
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Par défaut
    je pencherais largement pour la première option... elle permet de se dispenser de savoir ce qu'on traite comme information.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Merci pour vos réponses,

    Je viens de passer par le mode binaire de md5sum et le code binaire de la clé n'est pas long du tout (16 bytes). Donc 128 bits => 16 bytes en effet. Mais ça semble tout petit comme ça !!!

    Apparemment il est grand, bon je vais pouvoir utiliser gmp puisque je l'ai installé et testé à l'occasion. J'espère que ça prendre pas trop de mémoire vive. Sinon ça paraît totalement ..... abérrant qu'il n'y ait pas de fonction pour les puissances avec mpz_class !!! J'ai bien regardé 3x la doc sans vraiment comprendre, il n'expliquent pas vraiment. Si finalement je n'utilise pas gmp au vu de ce que vous allez me conseillez c'est pas grave ça pourrait toujours servir.

    Voilà donc, amaury pouly tu parles de résultat indéterminé ? Je ne comprends pas... j'aimerais bien que tu m'expliques pourquoi mon code est horrible pour le corriger ? Pour ce qui est de la mémoire j'utiliserais gmp s'il le faut.

    Salut Médinoc, en parlant de tableaux d'octets qu'est-ce que tu veux dire exactement ? Il me semblait que "buffer" dans mon code aggissait déjà en tant que tel, ce n'est pas le cas ? Surtout que comme le dis dis reptils (salut au passage), je ne traîte pas forcément du texte mais aussi bien des images, des octets de tout type en bref ! Et pour enfoncer le clou, j'ai fais une opération complète (à savoir chiffrer puis déchiffrer) et j'ai obtenu avec du texte, le texte de départ (testé avec un md5sum). Je ne vois pas où des \0 auraient pu intervenir dans mon fichier vu qu'il est lu binairement (ios::binary ?).

    Sinon je pensais régler ce problème de clé binaire en l'écrivant directement en binaire dans le code, ça pourrait jouer non ? Du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *key = "\x9cdfb439c7876e703e307864c9167a15";
    J'ai essayé comme ça, mais je ne sais pas si c'est le résultat espéré? C'est à dire que 9cd... soit pris comme du hex directement et convertit en binaire derrière ? Enfin bon je viens de regarder dans mon manuel et apparemment ça fonctionne que pour \xhhh (3 chiffre hex donc). Dommage !

    Merci pour votre aide !

  16. #16
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Pour le XOR (^) bit a bit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     0101
    XOR
     0111
    =
     0010
    XOR
     0111
    ------
     0101 ---> donnée de départ
    Normalement c'est comme ça que ça marche, peut importe le type de données qu'on manipule.

  17. #17
    Membre éprouvé Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Par défaut
    Utiliser des doubles c'est horrible si on a besoin de précision tout simplement parce qu'il y a des arrondis à toutes les étapes. D'une part, entre deux machines différentes, si par malheur le mode d'arrondis n'est pas le même, les résultats d'un MEME calcul peuvent être(et seront probablement) différent. D'autre part, en flottant, aucune opération n'est associative(même pas + ), donc si par malheur deux compilos compilent le code différemment(notamment avec des optimisation), le code généré sera différent donc le résultat aussi.
    Bref les doubles ça ne s'utilisent que pour des calculs approchés

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Merci pour vos conseils,

    Je pense avoir réussi à obtenir ce que je voulais. C'est à dire que ma clé est convertie en nombre qui est inscrit donc en byte dans la mémoire. Ma clé une fois convertie en décimal est "208521104953385306818825064957145938528". C'est bien l'ordre de grandeur attendu. J'ai fais tout mes tests tout semble marcher.

    Maintenant c'est est-ce que l'opération XOR fonctionne comme je le voudrais ? C'est à dire que qu'il fait bien un XOR sur les bits de ma clé sur ceux des données. Voici la dernière version de mon code :

    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
    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
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <math.h>
    #include <gmpxx.h>
     
    using namespace std;
     
    // Chiffrage
    // -- selon une clé char
    void crypt(char *text, int length, char *key, char *crypted) {
         int j = 0;
         for (int i = 0; i < length; i++) {
             // Lis la clé en boucle
             if (i%strlen(key) == 0) {
                   j=0;
             }
             // XOR
             crypted[i] = text[i] ^ key[j];
             j++;
         }
    }
     
    // -- selon une clé en binary mpz_class
    void crypt(char *text, int length, mpz_class key, char *crypted) {
         int j = 0;
         // Met dans un string (nombre base 10) le grand nombre
         // pour être utilisé lors du XOR
         string keychar = key.get_str(10);
         cout << keychar << endl;
         //const char *keychar = keystring.c_str();
         //sprintf(keychar, "%39.0i", key);
         for (int i = 0; i < length; i++) {
             // Lis la clé en boucle
             if (i%keychar.length() == 0) {
                   j=0;
             }
             // XOR
             crypted[i] = text[i] ^ keychar[j];
             j++;
         }
    }
     
    // Puissance avec des mpz_class
    mpz_class gmppow(mpz_class X, mpz_class Y) {
        mpz_class final=X;
        for (mpz_class i=1; i < Y; i++) {
            final = final*X;
        }
        return final;
    }
     
    // Conversion d'un char hex en mpz_class (int donc binaire)
    mpz_class convert_key_binary(char *key) {
         mpz_class result;
         result = 0;
         for (unsigned int i = 0; i < strlen(key); i++) {
             mpz_class tmp;
             // On lit de droite à gauche (inverser)
             char car = key[ i ];
             switch ( car ) {
                    case '0': tmp = 0; break;
                    case '1': tmp = 1; break;
                    case '2': tmp = 2; break;
                    case '3': tmp = 3; break;
                    case '4': tmp = 4; break;
                    case '5': tmp = 5; break;
                    case '6': tmp = 6; break;
                    case '7': tmp = 7; break;
                    case '8': tmp = 8; break;
                    case '9': tmp = 9; break;
                    case 'a': tmp = 10; break;
                    case 'b': tmp = 11; break;
                    case 'c': tmp = 12; break;
                    case 'd': tmp = 13; break;
                    case 'e': tmp = 14; break;
                    case 'f': tmp = 15; break;
                    default : cout << "Error"; return 0;
             }
             // Aditionne selon la règle de la position car*(16^pos)
             result += tmp*( gmppow(mpz_class(16), ((strlen(key)-1)-i)) );
         }
         return result;
    }
     
    int main(int argc, char *argv[])
    {
        // Prend en paramètre fichier src, fichier dst
        if (argc != 3) {
             cout << "Usage: " << argv[0] << " <fichier src> <fichier dst>" << endl;
             system("PAUSE");
             return 0;
        }
        else {
             cout << "Fichier d'entree: \t" << argv[1] << endl;
             cout << "Fichier en sortie: \t" << argv[2] << endl;
        }
        char *filename_in = argv[1];
        char *filename_out = argv[2];
     
        // Ouverture des fichiers
        fstream file_in(filename_in, ios::in|ios::binary);
        fstream file_out(filename_out, ios::out|ios::binary);
        if (!file_in || !file_out) {
              cout << "Impossible d'ouvrir !";
              system("PAUSE");
              return 0;
        }
     
        // Clé en char hex
        //char *key = "9cdfb439c7876e703e307864c9167a15";
        string keyString;
        cout << "Entrez la clef de chiffrage: ";
        getline(cin, keyString);
        char *key = (char *) keyString.c_str();
        int tmplen = strlen(key);
        // Teste si la longueur est puissance de 2
        if ( ((tmplen & -tmplen) xor tmplen) != 0 ) {
              cout << "La longueur de la cle doit etre une puissance de 2." << endl;
              system("PAUSE");
              return 0;
        }
     
        // Convertit la clé en binaire gros int (mpz_class)
        mpz_class keyhex = convert_key_binary(key);
        cout << keyhex << endl;
     
        // Variable de lecture
        int iter = 0;
        const int tranche = 192;
        char buffer[tranche];
     
        // Determine la longueur du fichier
        file_in.seekg(0, ios::end);
        int file_inlength = file_in.tellg();
        file_in.seekg(0, ios::beg);
     
        // Lis par tranche de tranche octets
        while (iter*tranche < file_inlength) {
              // Octet actuel
              int readByte;
              readByte = tranche;
              // Faut-il reduire la tranche de read/write
              if (iter*tranche+tranche > file_inlength)
                 readByte = file_inlength-iter*tranche;
              strcpy(buffer, "");
              // Lis une tranche d'octets, chiffre et écrit
              file_in.read(buffer, readByte);
              char tmp[readByte];
              crypt(buffer, readByte, keyhex, tmp);
              file_out.write(tmp, readByte);
              iter++;
        }
     
        // Ferme les fichiers
        file_in.close();
        file_out.close();
     
        cout << "\nFini\n";
        system("PAUSE");
        return 0;
    }
    L'opération xor entre un string et un char se passe-t-elle comme entre char (tableau binaire) ? C'est très important que ce soit bien une clé 128 bits qui soit utilisé et non la chaîne en char, pour des raisons évidentes: que ce soit universel avec d'autres chiffreur XOR (peut-être aurait-je à faire le même type dans un autre langage).

    Merci beaucoup.

  19. #19
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    pour définir ta clé, tu peux la définir de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char key[16] = { 0x9c, 0xdf, 0xb4, 0x39, 0xc7, 0x87, 0x6e, 0x70, 0x3e, 0x30, 0x78, 0x64, 0xc9, 0x16, 0x7a, 0x15 };
    Pour le xor, tu peux le faire octet par octet, en parcourant ta clé et le fichier en parrallèle.

    Tu ne dois pas utiliser les fonctions sur les chaînes de caractères (strlen et consorts), car tu ne travaille pas avec des chaînes de caractères. La bonne solution, c'est de passer la taille de ta clé à ta fonction crypt.

    Enfin, je ne sais pas dans quel contexte tu comptes utiliser cela, mais ce cryptage n'est pas fiable du tout pour un grand texte et une petite clé.

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    pour définir ta clé, tu peux la définir de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char key[16] = { 0x9c, 0xdf, 0xb4, 0x39, 0xc7, 0x87, 0x6e, 0x70, 0x3e, 0x30, 0x78, 0x64, 0xc9, 0x16, 0x7a, 0x15 };
    Merci bien ! Je ne connaissais pas. Il y a moyen d'utiliser cette définition avec une clé entrée au clavier avec getline() ?

    Citation Envoyé par white_tentacle Voir le message
    Pour le xor, tu peux le faire octet par octet, en parcourant ta clé et le fichier en parrallèle.
    Je pensais que mon code faisait octet par octet ! C'est pas le cas de cette boucle for ici ? :

    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
    // -- selon une clé en binary mpz_class
    void crypt(char *text, int length, mpz_class key, char *crypted) {
         int j = 0;
         // Met dans un string (nombre base 10) le grand nombre
         // pour être utilisé lors du XOR
         string keychar = key.get_str(10);
         cout << keychar << endl;
         //const char *keychar = keystring.c_str();
         //sprintf(keychar, "%39.0i", key);
         for (int i = 0; i < length; i++) { // <== ICI boucle octet par octet ?
             // Lis la clé en boucle
             if (i%keychar.length() == 0) {
                   j=0;
             }
             // XOR
             crypted[i] = text[i] ^ keychar[j]; // <== ICI 1 octet ^ 1 octet non ?
             j++;
         }
    }
    Citation Envoyé par white_tentacle Voir le message
    Tu ne dois pas utiliser les fonctions sur les chaînes de caractères (strlen et consorts), car tu ne travaille pas avec des chaînes de caractères. La bonne solution, c'est de passer la taille de ta clé à ta fonction crypt.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void crypt(char *text, int length, mpz_class key, char *crypted) {
    [...]
     
             // Lis la clé en boucle
             if (i%keychar.length() == 0) { // <-- ICI je ne devrais pas utiliser length ???
    Comme je l'ai dis, à cause du typage je suis obligé de convertir mon grand nombre stocké dans key en un string, sinon le XOR ne passe pas (problème de typage, non compatible). C'est peut-être inadapté mais j'ai pas trouvé mieux

    Citation Envoyé par white_tentacle Voir le message
    Enfin, je ne sais pas dans quel contexte tu comptes utiliser cela, mais ce cryptage n'est pas fiable du tout pour un grand texte et une petite clé.
    Dans un contexte où les données doivent être protegées à ce que les gens normaux n'y accédent pas. Je parle d'utilisateur lambda voir peut-être plus. Donc je pense qu'un tel chiffrage est bien suffisant. Je ne pense pas tomber sur des crackers ou autres professionnels du déchiffrage parce que les données n'ont pas beaucoup de valeurs, elles ne sont pas confidentiels. C'est simplement qu'il a fallu du travail pour réunir ces informations et le chiffrer me semble une bonne méthode afin d'empêcher n'importe qui d'y accéder sans le programme. Rien de plus.

    J'aimerais bien avoir quelques commentaires si mon code afin de l'améliorer et, moi, pour apprendre. J'ai l'impression que vous faîte des commentaires mais sans jeter un oeil au code, désolé si je me trompe. J'ai vraiment envie de progresser et je suis sûr que il y a pleins de choses à corriger qui vous semble évidente dans mon code.

    Merci à vous.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. parser un fichier avec xerces
    Par traiangueul dans le forum XML/XSL et SOAP
    Réponses: 9
    Dernier message: 02/02/2004, 18h14
  2. Réponses: 8
    Dernier message: 14/11/2003, 22h51
  3. Dossier ou Fichier avec ShellListView
    Par MoussDiouf dans le forum Langage
    Réponses: 6
    Dernier message: 14/06/2003, 12h33
  4. [VB6] [Réseau] Récupérer la taille d'un fichier avec inet
    Par pcpunch dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 20/02/2003, 21h38
  5. enregistrer dans un fichier avec une appli mdi
    Par ferrari dans le forum C++Builder
    Réponses: 4
    Dernier message: 05/05/2002, 15h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo