Aller au menu - Aller au contenu

Icône Hacher avec Qt

Mise à jour : 16/12/2010
Difficulté : Facile Facile Creative Commons BY-NC-SA
230 visites depuis 7 jours, dont 24 sur ce chapitre classé 394/786
Dans ce chapitre, je vais vous expliquer comment hacher des données avec Qt !

Hacher ? C'est quoi ça ? Partager dans plusieurs variables ?

Mais non, rien à voir ! Si vous préférez, le hachage est une méthode de chiffrage ne permettant pas de décryptage.

Qt permet de hacher très facilement des données ! Je vais vous montrer comment faire tout au long de ce tuto. Prêt ? Suivez moi !
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Théorie

Comme je le disais plus haut, vous allez ici apprendre à hacher avec Qt !

Le hachage, pour faire simple, est un "chiffrage" qui ne peut pas être déchiffré.

Je vous vois déjà me demander :

Mais... Si on chiffre, c'est bien pour pouvoir déchiffrer après non ? Si on a pas l'intention de se resservir des données, autant ne pas les enregistrer !

En fait, le hachage ne permet pas de "chiffrer" toutes vos données. Vous pouvez, évidemment, mais il serait un peu inutile de hacher par exemple les meilleurs scores de votre jeu, vu que vous ne pourriez pas les afficher ensuite ! En fait, le hachage est surtout utilisé pour "chiffrer" des données qui seront à nouveau entrées par l'utilisateur, comme son mot de passe.

Ben oui, mais bon... Son mot de passe, on aura quand même besoin de le déchiffrer pour vérifier qu'il est bon ! Non ? :euh:

Pas forcément ! Prenons un exemple : On veut vérifier que 3x2 est égal à 6. On a alors deux possibilités de le vérifier.
  • Soit on fait 3x2, on obtient 6, et on se rend alors compte que 6 = 6, et que donc 3x2 = 6
  • Soit on fait 6/2 et 3x2/2, et on se rend compte que 3 = 3, et que donc 3x2 = 6.

Si on applique cet exemple à notre mot de passe appelé ici "MdP" et son chiffrage appelé ici "MdP chiffré" (ici, pour illustrer les deux exemples, on dira que le mot de passe est chiffré et non haché, donc déchiffrable) , et qu'on a une fonction de chiffrage appelée "chiffre" et une de déchiffrage, "déchiffre" :
  • Soit on fait chiffre(MdP), et on se rend compte que chiffre(MdP) = MdP chiffré
  • Soit on fait déchiffre(MdP chiffré), et on se rend compte que MdP = déchiffre(MdP chiffré)

Seulement, avec un hachage, on ne peut pas déchiffrer. Sans la fonction "déchiffrer", il ne nous reste donc plus que la première possibilité !

Donc, pour résumer, pour comparer des données à des données hachées, on hache les données de la même manière que celles déjà hachées, et on compare les deux.

C'est bien joli, tout ça, mais après tout, à quoi ça me servirait ? Si l'utilisateur entre son mot de passe, il sera stocké sur son DD, donc à priori, il y a pas trop de risques de piratage !

Tout faux ^^ . Déjà, qui vous dit que l'utilisateur ne veut pas éviter que ses parents/ses fils/son chien n'accèdent à son mot de passe ? Ça peut donc être utile de hacher un mot de passe, même sur son propre disque dur.

Ensuite, imaginez que vous programmez une messagerie instantanée, par exemple (si vous préférez, un genre d'MSN). Tous les comptes créés seront sûrement stockés soit dans un fichier sur votre serveur, soit dans une base de données.

Si un pirate accédait à ce fichier ou cette base de données, vous imaginez un peu la catastrophe, dans le cas où les mots de passe sont en clair ! Il aurait alors accès à tous les comptes de tous les utilisateurs de votre programme :waw: ! Alors que vu qu'un hash (on appelle "hash" le résultat d'un hachage) est indéchiffrable... Le pirate ne pourra rien en faire.

Prêts pour passer au codage ? Alors, c'est parti !

Hacher avec Qt

Tous les liens portant le nom d'une classe Qt seront des liens vers la doc' de Qt 4.6 !


Bon, c'est fini avec la théorie, cette fois, on va vraiment programmer ! :D

Pour hacher, on va utiliser une classe du doux nom (un peu long aussi) de QCryptographicHash. Tout se fera via la méthode statique hash.
Voyons déjà son prototype :

Code : C++
1
QByteArray QCryptographicHash::hash ( const QByteArray & data, Algorithm method )   [static]


On voit donc plusieurs choses :
  • Cette méthode est statique, mais ça je vous l'ai déjà dit :) . Pour rappel, une méthode statique peut être appelée sans avoir créé d'objet, avec Classe::methode() .
  • La méthode retourne un QByteArray, soit un tableau d'octets.
  • Elle prend en premier paramètre un autre QByteArray, qui ne sera pas modifié (const).
  • Elle prend en second paramètre Algorithm, qui est une énumération définie dans QCryptographicHash.

Détaillons ses paramètres :
  • data est tout simplement ce que la fonction va chiffrer.
  • method est la méthode de hachage. Car oui, il y a plusieurs méthodes !

Reprenons donc le code de base de Qt :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <QApplication>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget w;

    w.show();
    return app.exec();
}


On ne va ici utiliser que le main.

Ajoutons la fonction de hachage :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <QApplication>
#include <QWidget>
#include <QCryptographicHash>
#include <QByteArray>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget w;

    QByteArray ba = QCryptographicHash::hash(/*arguments*/);

    w.show();
    return app.exec();
}


Eh, au fait, tu nous as toujours pas dit qu'est-ce qu'on met comme arguments ! Et si j'ai pas de QByteArray, mais que je veux hacher... Je sais pas, moi ! Une chaine !
Et puis, d'abord, on met quoi en deuxième argument, concrètement ?


Je vais commencer par répondre à la première, parce que c'est la plus simple pour faire ça dans l'ordre :

Pour envoyer une chaine de caractères (ce qui sera le cas si on veut hacher un mot de passe, par exemple), il faut que ça soit une QString, et envoyer à hash() sa conversion en UTF-8 :

Code : C++
1
QCryptographicHash(chaine.toUtf8(), /*arg 2*/); // chaine est une QString


Ensuite, pour les différentes méthodes. Qt en propose à ce jour 3 :
  • En MD4 (wikipedia) : Cette méthode n'est pas sûre, et peut être cassée, mais elle a l'avantage d'être rapide. Dans l'absolu, mieux vaut éviter de l'utiliser, sauf si la rapidité de l'algorithme est vraiment importante. Pour l'utiliser, le second paramètre est QCryptographicHash::Md4.
  • En MD5 (wikipedia) : Une méthode assez sûre, bien qu'elle ne le soit de moins en moins avec l'apparition de "dictionnaires Md5/texte", et la possibilité de générer des collisions (merci à Phacog pour l'info sur les collisions !). Pour l'utiliser, le second paramètre est QCryptographicHash::Md5.
  • En SHA-1 (wikipedia) : La méthode considérée comme la plus sûre des trois, et celle que je vous conseille d'utiliser. Pour l'utiliser, le second paramètre est QCryptographicHash::Sha1.


Essayez-donc de hacher en SHA-1 une chaine appelée chaine et définie un peu plus haut dans le code ! À vous de jouer !

Secret (cliquez pour afficher)
Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <QApplication>
#include <QWidget>
#include <QCryptographicHash>
#include <QByteArray>
#include <QString>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget w;

    QString chaine="Ceci sera haché.";
    QByteArray ba = QCryptographicHash::hash(chaine.toUtf8(), QCryptographicHash::Sha1);
    

    w.show();
    return app.exec();
}


Et voilà ! Vous avez haché votre chaine !

J'ai essayé d'afficher le QByteArray dans un QMessageBox. Ça m'affiche un truc bizarre, plein de caractères spéciaux. Ça ressemble à ça un hash ? :euh:


Non :D . C'est normal que ça affiche ça, car le retour de hash n'est PAS une QString ! Pour le convertir en QString, il faut utiliser la méthode toHex() :
Code : C++
1
QString hash = ba.toHex();


Là, vous obtiendrez une chaine qui ressemble à 0e6d2d873c7ec7ce703e48b009723c9b820f29bd. Eh bien, ceci est votre hash !

Si on résume le code, on a donc :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <QApplication>
#include <QWidget>
#include <QCryptographicHash>
#include <QByteArray>
#include <QString>
#include <QMessageBox>


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget w;

    QString chaine="Ceci sera haché."; // On crée la chaine à hacher
    QByteArray ba = QCryptographicHash::hash(chaine.toUtf8(), QCryptographicHash::Sha1); // on la hache

    QString out=ba.toHex(); // on convertit le hash en QString
    QMessageBox::information(&w, "test", out); // on l'affiche

    w.show();
    return app.exec();
}


Plus de sécurité ?



Comment ça, "plus de sécurité" ? Tu nous avais dit que c'est indécryptable ! Tu nous aurais menti ? :colere2:


D'une certaine manière, non. En effet, c'est, à proprement parler, indéchiffrable. Mais... Il existe des correspondances entre les mots courants et leurs hachages MD5/SHA-1 ou autres. Évidemment, ces bases de données ne sont pas complètes ! Mais si votre hash est dedans... Pour cela, il a été mis au point une technique permettant d'assaisonner les aliments de rendre ces méthodes quasi-inutiles, et de rendre plus difficiles les attaques par force brute (test de toutes les combinaisons) : le salage (wikipedia).

Cette technique est très simple : pour compliquer les données à hacher, on rajoute avant ou après (ou les deux) des données qui sont toujours les mêmes. Ces données sont appelées sels.

Ainsi, si on veut hacher la chaine "siteduzero" avec le sel "GRAINDESEL" (où GRAINDESEL est un define d'une chaîne de caractères, méthode que je vous recommande) avant, on mettra en argument "data" de la fonction hash QString(GRAINDESEL"siteduzero").toUtf8

Il y a même encore mieux : hacher les sels eux-mêmes, de préférence avec un autre algorithme de hachage (par exemple, MD5 si vous utilisez du SHA-1 pour le hash final). Vous pouvez faire de même avec votre chaîne à chiffrer elle même :

Code : C++
 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
#include <QApplication>
#include <QWidget>
#include <QCryptographicHash>
#include <QByteArray>
#include <QString>
#include <QMessageBox>

#define SEL_AVANT "D4Dqdz68$E" // une technique approuvée pour vos sels est de s'endormir sur le clavier.
#define SEL_APRES "7HHo£hh7YH" // Si ils ne veulent rien dire, c'est mieux.


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget w;

    QString chaine="Ceci sera haché."; // On crée la chaine à hacher
    QByteArray ba = QCryptographicHash::hash(QByteArray(QCryptographicHash::hash(QString(SEL_AVANT).toUtf8(), QCryptographicHash::Md5) +
                                                        QCryptographicHash::hash(chaine.toUtf8(), QCryptographicHash::Md5) +
                                                        QCryptographicHash::hash(QString(SEL_APRES).toUtf8(), QCryptographicHash::Md5)), QCryptographicHash::Sha1); // on la hache

    QString out=ba.toHex(); // on convertit le hash en QString
    QMessageBox::information(&w, "test", out); // on l'affiche

    w.show();
    return app.exec();
}


Nous sommes donc au final arrivés à un code pas si gros, mais très sécurisé ! Par contre, il faut savoir une chose : plus vous mettez de sécurités, sels, hachages de sels, etc., plus le temps de calcul est long ! Pour hacher vos sels, l'utilisation du MD4 est éventuellement possible, si vous trouvez que le temps de calcul est trop long (mais franchement, vous devriez même pas le voir passer, sauf si vous générez 100 000 hashs, et encore).

Q.C.M.

Quelle est/sont la/les classe(s) de Qt permettant de hacher des données ?
Lequel de ces algorithmes est rapide, mais peu sécurisé de nos jours ?
Comment s'appellent des données qu'on ajoute à celles qui vont être hachées pour accroitre la sécurité de ce hachage ?

Statistiques de réponses au QCM

Eh bien voilà ! Vous êtes maintenant des pros du hachage avec Qt !
Chapitre précédent Sommaire Chapitre suivant

Partager

19 commentaires pour "Hacher avec Qt"
Note moyenne : 3.67 / 4 (18 votes)
Pseudo Commentaire
Hors ligne Terbaddo # Posté le 16/12/2010 à 19:36:29
Stallman hater
Avatar

Ville : Garges-lès-gonesse
Pays : France métropolitaine

Hasher
 
Hors ligne tobast # Posté le 16/12/2010 à 19:46:54
if(!geek) exit(EXIT_FAILURE);
Avatar

Yep. In english :D .
Mais en français, c'est bien hacher, je crois. Une confirmation ?
 
Hors ligne Phacog # Posté le 16/12/2010 à 21:32:41
J'ai glissé chef...
Avatar

Oui, le terme correct en français est bien "hacher". Par contre ce qui me pique les yeux est l'utilisation des termes "crypter" et "decrypter".

Pour info le verbe "crypter" n'existe pas dans la langue française, on utilise à la place le terme "chiffrer", l'opération inverse est tout logiquement "déchiffrer". Par contre "décrypter" existe bel et bien mais n'a pas le même sens que déchiffrer : décrypter un message chiffré consiste à retrouver le message clair sans connaitre la clef de chiffrement utilisée.

Sinon, deux petites remarques en passant :

Citation
En MD5 (wikipedia) : Une méthode assez sûre, bien qu'elle ne le soit de moins en moins avec l'apparition de "dictionnaires Md5/texte". Pour l'utiliser, le second paramètre est QCryptographicHash::Md5.


Effectivement, la fonction MD5 n'est plus très sure, mais cela n'est pas du à l'apparition de "dictionnaire MD5/texte", de tels dictionnaires existent aussi bien pour SHA-1. Avecl'algorithme MD5 on arrive à creer volontairement deux message ayant le même haché (des collisions). Au passage l'algortihme SHA-1 commence lui aussi à montrer des signes de faiblesse (d'ailleurs on ne trouve pas les algos SHA-256 et SHA-512 ou d'autre dans QT ?)

La deuxième remarque concerne la phrase suivante :
Citation
Essayez-donc de crypter en SHA-1 une chaine appelée chaine et définie un peu plus haut dans le code ! À vous de jouer !

Bon je vais pas refaire mon couplet ur le terme "crypter", mais ici il est encore plus choquant : une fontcion de hachage n'est pas une fonction de chiffrement, donc on ne peut pas chiffrer (et encore moins "crypter") avec SHA-1. On hache tout simplement.

Si le ciel est un parapluie, où sont les baleines ?
 
Hors ligne tobast # Posté le 16/12/2010 à 22:11:47
if(!geek) exit(EXIT_FAILURE);
Avatar

Merci à toi Phacog !

Je corrigerai toutes ces fautes dès que je le pourrai... Dans les versions actuelles de Qt, il n'existe que le MD4, le MD5 et le SHA-1...
 
Hors ligne ProgramFiles # Posté le 07/06/2011 à 09:11:15
Avatar
Flux RSS

Très simple et compréhensif même si quelques erreurs paraissent.

Mon projet de lecteur de flux audio (Webradio): GumiXRadio
Mon projet de modificateur de fichier AssistantMic.artwork: GumiXArtwork


Image utilisateur
 

Voir tous les commentaires