Chiffrement AES avec cryptoPP

Le problème exposé dans ce sujet a été résolu.

Salut !

J’ai un souci avec cryptoPP.

J’essaye d’adapter le code suivant1 pour qu’il fonctionne avec des fichiers à la place de strings:

 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
AutoSeededRandomPool prng;

SecByteBlock key(AES::DEFAULT_KEYLENGTH);
prng.GenerateBlock( key, key.size() );

byte iv[ AES::BLOCKSIZE ];
prng.GenerateBlock( iv, sizeof(iv) );

string plain = "CBC Mode Test";
string cipher, encoded, recovered;

/*********************************\
\*********************************/

try
{
    cout << "plain text: " << plain << endl;

    CBC_Mode< AES >::Encryption e;
    e.SetKeyWithIV( key, key.size(), iv );

    // The StreamTransformationFilter adds padding
    //  as required. ECB and CBC Mode must be padded
    //  to the block size of the cipher.
    StringSource ss( plain, true, 
        new StreamTransformationFilter( e,
            new StringSink( cipher )
        ) // StreamTransformationFilter      
    ); // StringSource
}
catch( const CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

// Pretty print cipher text
StringSource ss( cipher, true,
    new HexEncoder(
        new StringSink( encoded )
    ) // HexEncoder
); // StringSource
cout << "cipher text: " << encoded << endl;

/*********************************\
\*********************************/

try
{
    CBC_Mode< AES >::Decryption d;
    d.SetKeyWithIV( key, key.size(), iv );

    // The StreamTransformationFilter removes
    //  padding as required.
    //
    StringSource ss( cipher, true, 
        new StreamTransformationFilter( d,
            new StringSink( recovered )
        ) // StreamTransformationFilter
    ); // StringSource

    cout << "recovered text: " << recovered << endl;
}
catch( const CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

Voila où je suis arrivé:

 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
void AESCrypter::encrypt( QString input,  QString  output)
{
    const char* in = input.toStdString().c_str();
    const char* out = output.toStdString().c_str();

    std::cout <<"preparation... "<<in<<" will be  encrypted as "<<out<<"\n";

    try{
        CryptoPP::CBC_Mode< CryptoPP::AES >::Encryption e;
        e.SetKeyWithIV( m_key, m_key.size(), m_iv );


        CryptoPP::FileSource fs(in, true,
                                    new CryptoPP::StreamTransformationFilter( e,
                                        new CryptoPP::FileSink( out  )
                                    )// StreamTransformationFilter
                                ); // StringSource

    }

    catch( const CryptoPP::Exception& e )
    {
        std::cerr << e.what() << std::endl;
        return ;
    }


    std::cout <<"no error, "<<in<<" has been encrypted without any issues as "<<out<<"\n";
}

Et je l’utilise comme ça :

1
2
3
//main.cpp 
AESCrypter crypter{};
crypter.encrypt(argv[1], "/Users/d3m0t3p/t1Encrypted.txt");
Exemple :

./crypto /Users/d3m0t3p/t1.txt
preparation, /Users/d3m0t3p/t1.txt will be encrypted as /Users/d3m0t3p/t1Encrypted.txt
no error, /Users/d3m0t3p/t1.txt has been encrypted without any issues as

Les erreurs :
  1. le text de sortie montre que le contenu de out est changé.
  2. le fichier encrypté créé se trouve à coté de l’exécutable et non à la destination du chemin
  3. le nom de fichier ressemble à quelques chose comme ça ]%B5G}%B5%D0&@"s0%DFRncrypted.txt à la place du nom attendu

Si je créer un fichier avec le même chemin mais en utilisant QFile le fichier est créé au bon endroit avec le bon nom.

Est-ce un bug de cryptoPP ou je ne l’utilise pas correctement ?

+0 -0

Plop

Quelque chose comme xxx = output.toStdString().c_str(); est une très mauvaise idée. toStdString retourne un std::string, c_str() le contenu de std::string puis le std::string temporaire est supprimé. Et xxx pointe sur quelque chose qui n’existe plus.

Donc out et in devrait être des std::string et c_str() déplacé sur FileSink (si celui_ci ne supporte vraiment pas std::string).

Je viens de tester, le fichier est bien créer au bonne endroit avec un nom correcte !
J’ai pas réfléchis à la durée de vie de mes variables :o

Merci beaucoup
Je suppose que ça non plus je devrais pas faire alors:

QFileInfo(QFile(path)).fileName()
Mais comme c’est dans un slot (j’utilise Qt) je suis obligé d’avoir une variable membre QFile et un autre QFileInfo juste pour récupéré le nom ? C’est un peu beaucoup pour avoir le nom du fichier je trouve.

+0 -0

Je suppose que ça non plus je devrais pas faire alors:

QFileInfo(QFile(path)).fileName()

Il n’y a pas de problème ici. Comme l’ensemble fait partit de la même expression QFile est détruit après la destruction de QFileInfo. De toute façon, QFileInfo ne garde pas le QFile et tu peux directement utiliser path (QFile sera implicitement construit).

Mais comme c’est dans un slot (j’utilise Qt) je suis obligé d’avoir une variable membre QFile et un autre QFileInfo juste pour récupéré le nom ? C’est un peu beaucoup pour avoir le nom du fichier je trouve.

d3m0t3p

Pourquoi des variables membres ? Un slot est une fonction avec ses propres variables locales.

Pourquoi des variables membres ? Un slot est une fonction avec ses propres variables locales.

jo_link_noir

Lorsque je clique sur le bouton, le slot est appelé, un QFileDialog permet de choisir le fichier à encrypter, mais je change le texte d’un label pour qu’il ait le nom du fichier choisis.
Selon la doc de setText il prend une référence d’un QString. Mais à la fin de mon slot mon nom de fichier (filename) créé avec QFileInfo(QFile(path)).fileName() n’existe plus et pourtant le label a toujours une référence dessus non ?

Donc ceci label->setText(QFileInfo(QFile(path)).fileName()); est problématique il me faut donc avoir une variable membre dans ma classe qui contient le nom de fichier, pour qu’à la fin du slot le label pointe toujours vers quelque chose qui existe.

+0 -0

Lorsque je clique sur le bouton, le slot est appelé, un QFileDialog permet de choisir le fichier à encrypter, mais je change le texte d’un label pour qu’il ait le nom du fichier choisis.
Selon la doc de setText il prend une référence d’un QString. Mais à la fin de mon slot mon nom de fichier (filename) créé avec QFileInfo(QFile(path)).fileName() n’existe plus et pourtant le label a toujours une référence dessus non ?

d3m0t3p

Non. QLabel fait une copie. Tu imagines si à chaque fois que tu fais un label.setText("abc"), il faille mettre "abc" dans une variable membre ?

Il me semble qu’avec Qt la règle est: si c’est un pointeur alors la durée de vie est gérée par l’extérieur. Si c’est une référence, alors la fonction ne garde pas la référence, ou au besoin fait une copie. (EDIT: sauf les widgets qui ont leur propre système.)

Donc pas de problème ici.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte