Dans mon billet sur les flops et le temps pour casser un password par brute force. Je prenais uniquement en compte la puissance en FLOPS sans prendre en compte le type de hash et les itérations. J’ai récemment parlé dans un billet du temps nécessaire à un supercalculateur pour casser un mot de passe issus d’une fonction de hash. En partant du postulat : 1 FLOPS = 1 hash. A présent je vais essayer de calculer le temps nécessaire à ce même supercalculateur pour casser une clé réalisé non pas seulement un hash mais avec une fonction de type PBKDF2.
Le PBKDF2 (Password-Based Key Derivation Function) est une fonction de dérivation de clé qui est implémenté dans la majorité des logiciel de chiffrement de disque. C’est aujourd’hui la meilleure référence en matière de sécurité pour la création de clé de chiffrement. Il est basé sur ces éléments :
- Un algorithme de HMAC (SHA512, RIPEMD, WHIRLPOOL,etc)
- Un mot de passe
- De la Salt pour luter contre une attaque rainbow table
- Des itérations pour ralentir la génération de clé
Ces itérations sont très importantes car elles permettent d’accroitre considérablement le temps nécessaire au test de toutes les combinaisons d’un mot de passe. Et c’est sur cela que ce billet va se concentrer.
Je vais reprendre l’excellent travail d’explication du fonctionnement de Truecrypt de Bjorn Edstrom et ses fonctions en python. Dans un premier temps je vais chercher à générer une clé PBKDF2-PKCS#5, puis dans un second temps je vais chercher à calculer le temps qu’il faut pour la générer la clés en fonctions des différents éléments la composant.
1 / Les algorithmes de hachage
Truecrypt utilise soit le RIPEMD-160 soit du WHIRLPOOL soit du SHA512 comme générateur de hash. Le RIPEMD-160 et le WHIRLPOOL sont tous les 2 issus du standard ISO/IEC 10118-3:2004 alors que le SHA512 est issus du FIPS PUB 180-2. Dans les 2 cas se sont des standards récent qui date respectivement de 2004 et 2002.
Le RIPEMD est considéré comme le plus faible des 3 car il génère un résultat que sur 160bits, alors que les 2 autres font un hash de 512bits. Pour palier à ce manque, Truecrypt fait 2000 itérations à cet algorithme au lieu de 1000 comme pour les 2 autres.
Le SHA-512 est de la famille du SHA-2 qui est dérivé du SHA-1. Le SHA-1 possède des failles qui ont été découverte en 2005, sont remplacement par le SHA-3 est en cours.
2 / Hash, HMAC et PBKDF2
Voici rapidement l’explication des différentes fonctions.
Le hash est l’empreinte d’un mot de passe généré par un algorithme à sens unique (SHA, MD5, RIPEMD, Whirlpool, etc).
Le HMAC est une fonction de hash qui va créer l’empreinte d’un texte tout en le combinant avec un mot de passe.
Une fonction PBKDF2 combine un HMAC, un texte, de la salt et des itérations.
3 / Générer le hash d’un password en python
Tout d’abord je vais chercher à savoir combien de temps prend mon ordinateurs pour générer le hash d’un password. Pour cela il faut télécharger d’abord les 2 librairies ripemd et whirlpool qui ne sont pas implémenté par défaut en python contrairement au SHA512.
Puis dans un SHELL python on va les tester :
import whirlpool
whirlpool.new("artiflo.net").hexdigest()
'220f227652e6af8b180697d416d387e73917c4d8a69360dd0e5dd5520dbf1684b09883bd2b5dcc4ae75fa93765b8aa7484be225a43ce12ab3ff11d0b700da4eb'
import ripemd
ripemd.new("artiflo.net").hexdigest()
'b6fb9b189dc3089fb4565948f9187bf07bfa6323'
from hashlib import sha512
sha512("artiflo.net").hexdigest()
'fb5b25552b64cde7e901a2097a900835b96dff747b95ce97eaaeb8e3088abdbf9c2eb54f467e6c6c9f45c6b431552579a4cf21bdae92f6e7e915d4a70d639982'
Comme prévu, le hash généré par le RIPEMD ne fait que 160bits il est plus court que les hash de 512bits de SHA512 et Whirlpool.
Maintenant qu’on peut générer un hash, il faut timer l’opération en utilisant la fonction timeit de python (Le résultat est donnée en seconde) :
import whirlpool
import timeit
timeit.Timer(stmt='whirlpool.new("password").hexdigest()', setup='import whirlpool').timeit(1)
0.0012343376151203668
import ripemd
timeit.Timer(stmt='ripemd.new("password").hexdigest()', setup='import ripemd').timeit(1)
0.00041234010131928941
from hashlib import sha512
timeit.Timer(stmt='sha512("password").hexdigest()', setup='from hashlib import sha512').timeit(1)
1.2002927298731502e-05
Tous ces résultat sont donnés en hexdigest() qui contrairement au digest() retourne uniquement des caractères hexadécimaux. Pour indication voici un tableau comparant les performances entre le hexdigest() et le digest().
| Type de retour | Temps WHIRLPOOL | Temps RIPEMD160 | Temps SHA512 |
| hash digest | 0,000718894 | 0,000397197 | 9,13E-06 |
| hash hexdigest | 0,001234338 | 0,00041234 | 1,20E-05 |
| Différence | 71,70% | 3,81% | 31,41% |
La différence est essentiellement du à l’implémentation de la fonction de hachage et son optimisation.

Arg… j’ai tout lu et je saigne du nez. Très belle analyse, ça a dû t’en prendre du temps pour faire tous ces calculs. J’aimerais voir la tête de ton jury si tu présentes ça à ta soutenance !
Merci ça fait plaisir
Surtout que ce sera en anglais. ahahahaha
Tu as bien raison mon bon Loic !
[...] Réponse : Le temps pour casser un mot de passe (et donc une clé) est très variable celon l’algorithme choisis. Mais un mot de passe de 14 caractères ASCII est aujourd’hui et pour les 10 prochaines années considéré comme sure. http://www.artiflo.net/2009/07/les-flops-les-cles-et-la-taille-des-mots-de-passe/ et aussi surtout http://www.artiflo.net/2009/08/pbkdf2-et-generation-des-cles-de-chiffrement-de-disque/ [...]
[...] temps nécessaire pour casser un mot de passe avec des supercalculateur dans ce billet, puis dans celui-ci avec PBKDF2. Je vais à présent m’intéresser dans cet article à essayer de définir le temps réel [...]
[...] L’année dernière, je décrivais dans ce blog, quelques résultats de mon mémoire sur le chiffrement de disque. Pour ceux qui l’aurait raté, c’est ici et surtout ici sur le PBKDF2. [...]