MD5, SHA-1 ou SHA-256 : quel algorithme de hachage choisir ?
Choisissez SHA-256 pour tout ce qui touche à la sécurité. MD5 et SHA-1 ne sont acceptables que là où personne n'a rien à gagner à forger une empreinte identique.
MD5, SHA-1 et SHA-256 font tous le même travail : ils transforment une entrée de n'importe quelle longueur en une empreinte courte et de taille fixe, appelée digest. La même entrée donne toujours la même empreinte, et la modification d'un seul bit change tout le résultat. Les trois se distinguent par la longueur de l'empreinte, par leur vitesse et surtout sur un point : peut-on produire délibérément deux entrées différentes qui ont la même empreinte ? Pour MD5 et SHA-1, cela a été fait publiquement. Pour SHA-256, non.
Les trois algorithmes en un coup d'œil
| MD5 | SHA-1 | SHA-256 | |
|---|---|---|---|
| Taille de l'empreinte | 128 bits, 32 caractères hexadécimaux | 160 bits, 40 caractères hexadécimaux | 256 bits, 64 caractères hexadécimaux |
| Publication | 1992 (RFC 1321) | 1995 (FIPS 180-1) | 2001, au sein de la famille SHA-2 |
| Collisions | Réalisables en pratique depuis 2004 | Réalisables en pratique depuis 2017 | Aucune attaque connue |
| Retrouver une entrée à partir d'une empreinte donnée | Aucune attaque pratique | Aucune attaque pratique | Aucune attaque pratique |
| Usage conseillé aujourd'hui | Checksums sans enjeu de sécurité, clés de cache | Compatibilité avec l'existant uniquement | Le choix par défaut pour tout nouveau projet |
Voici les empreintes complètes des cinq octets hello, telles que les affichent md5sum, sha1sum et sha256sum. Le générateur de hash présente ces mêmes valeurs côte à côte, avec en plus SHA-384 et SHA-512, pour un texte ou pour un fichier jusqu'à 50 Mo.
MD5 5d41402abc4b2a76b9719d911017c592
SHA-1 aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Ce que les bits supplémentaires apportent
La longueur de l'empreinte fixe le coût d'une attaque générique, c'est-à-dire une attaque qui traite la fonction comme une boîte noire. À cause du paradoxe des anniversaires, trouver deux entrées quelconques qui entrent en collision demande environ 2^(n/2) essais pour une empreinte de n bits : 2^64 pour MD5, 2^80 pour SHA-1 et 2^128 pour SHA-256. Trouver une entrée qui correspond à une empreinte précise (une préimage) demande environ 2^n essais.
Ces chiffres ne tiennent que tant que la conception de l'algorithme n'offre aucun raccourci. MD5 et SHA-1 ont tous deux des raccourcis pour les collisions : leur longueur ne dit donc plus tout. SHA-256 n'a aucun raccourci connu, et 2^128 dépasse de très loin toute la puissance de calcul qui existe.
Comment MD5 et SHA-1 ont été cassés
Une attaque par collision ne permet à personne d'inverser un hash. Elle permet à un attaquant de préparer à l'avance deux entrées différentes qui partagent la même empreinte, de faire accepter l'une comme digne de confiance, puis de lui substituer l'autre. La variante dangereuse est la collision à préfixe choisi (chosen-prefix) : l'attaquant choisit deux débuts qui ont un sens, par exemple deux certificats portant des noms différents, puis calcule des octets supplémentaires qui rendent les empreintes identiques.
- MD5, 2004 : Xiaoyun Wang et ses collègues publient des collisions MD5 réalisables en pratique.
- MD5, 2008 : une équipe de chercheurs exploite une collision MD5 à préfixe choisi pour créer un faux certificat d'autorité de certification que les navigateurs auraient accepté, parce qu'une autorité de certification commerciale signait encore ses certificats avec MD5.
- MD5, 2012 : le malware Flame utilise une collision MD5 pour forger un certificat de signature de code Microsoft.
- SHA-1, 2017 : Google et le CWI Amsterdam annoncent SHAttered, deux fichiers PDF différents ayant la même empreinte SHA-1. L'équipe indique environ 6 500 années-CPU et 110 années-GPU de calcul.
- SHA-1, 2020 : Gaëtan Leurent et Thomas Peyrin publient une collision SHA-1 à préfixe choisi réalisable en pratique et s'en servent pour usurper une clé PGP.
Les navigateurs ont cessé d'accepter les certificats TLS en SHA-1 en 2017, et le NIST a annoncé en décembre 2022 que SHA-1 devait être complètement abandonné d'ici fin 2030. Ni MD5 ni SHA-1 ne connaît d'attaque pratique par préimage : à partir d'une empreinte seule, personne ne sait retrouver une entrée qui la produit. C'est pourquoi les deux restent efficaces pour détecter des dommages accidentels.
Vitesse : mesurée, pas supposée
On présente souvent MD5 comme l'algorithme rapide. Nous avons haché les mêmes 256 Mo de données aléatoires avec Node 24 (OpenSSL 3.5) sur un seul ordinateur de bureau, trois fois pour chaque algorithme :
| Algorithme | Débit sur cette machine |
|---|---|
| SHA-1 | environ 1 000 Mo/s |
| MD5 | environ 730 Mo/s |
| SHA-512 | environ 690 Mo/s |
| SHA-256 | environ 460 Mo/s |
L'ordre dépend du processeur. Ce CPU ne dispose pas des extensions du jeu d'instructions SHA. Les processeurs qui en sont équipés accélèrent SHA-1 et SHA-256 au niveau matériel, et SHA-256 peut alors dépasser MD5. SHA-512 a battu SHA-256 ici parce qu'il travaille sur des mots de 64 bits. Sur des entrées courtes, l'écart disparaît : un million de hashs d'une courte adresse e-mail ont pris entre 1,8 et 2,1 secondes, que ce soit avec MD5, SHA-1 ou SHA-256, car le coût fixe de chaque appel pèse plus lourd que le hachage lui-même. La vitesse n'est presque jamais une vraie raison de choisir MD5.
Ce à quoi chacun sert encore
- MD5 : détecter une corruption accidentelle, dédupliquer vos propres fichiers, produire des clés de cache et des ETag, dialoguer avec des systèmes anciens qui l'exigent. Jamais pour des signatures, des certificats ou des contrôles d'intégrité lorsqu'un attaquant pourrait fournir le fichier.
- SHA-1 : les systèmes existants que vous ne pouvez pas encore modifier. Git nomme depuis longtemps ses objets avec SHA-1, à l'aide d'une implémentation renforcée qui détecte les attaques par collision connues, et prend aussi en charge des dépôts en SHA-256. HMAC-SHA1, l'algorithme par défaut derrière les codes TOTP des applications d'authentification, n'est pas concerné par les attaques par collision.
- SHA-256 : checksums de téléchargement, signatures numériques, certificats, HMAC, adressage par contenu et tout nouveau projet. Utilisez SHA-256 lorsqu'un checksum doit résister à une falsification, et réservez MD5 aux anciennes valeurs que vous devez encore retrouver.
Vous vérifiez un téléchargement ? Le vérificateur de checksum de fichier calcule le hash du fichier en local et vous indique à quel algorithme correspond le checksum que vous avez collé.
Aucun des trois ne doit stocker des mots de passe
Tous trois sont conçus pour être rapides, et la rapidité est précisément ce que recherche un attaquant qui essaie des milliards de mots de passe. Un sel empêche l'usage de tables précalculées, mais il ne ralentit pas les essais. Le stockage des mots de passe exige une fonction volontairement lente et, idéalement, gourmande en mémoire (memory-hard). Sur la même machine que ci-dessus :
| Fonction et paramètres | Temps par mot de passe |
|---|---|
| SHA-256, un appel depuis Node | environ 2,5 microsecondes |
| Argon2id, 19 Mio de mémoire, 2 itérations, 1 voie (lane) | environ 33 millisecondes |
| PBKDF2-HMAC-SHA256, 600 000 itérations | environ 270 millisecondes |
| scrypt, N=2^17, r=8, p=1 | environ 310 millisecondes |
Ces paramètres sont les minimums indiqués par l'OWASP Password Storage Cheat Sheet, qui recommande d'abord Argon2id, puis scrypt, bcrypt avec un facteur de coût de 10 ou plus pour les systèmes existants, et PBKDF2 lorsque la conformité FIPS-140 est exigée. Utilisez l'API de hachage de mots de passe de votre framework plutôt que d'en assembler une à partir d'un simple hash.
HMAC : quand un hash a besoin d'une clé
Pour prouver qu'un message provient de quelqu'un qui détient un secret, ne calculez pas sha256(secret + message). MD5, SHA-1 et SHA-256 sont tous exposés à l'extension de longueur (length extension) : connaître l'empreinte d'un message permet à un attaquant de calculer une empreinte valide pour ce message suivi de données supplémentaires, sans connaître le secret. HMAC (RFC 2104) évite ce problème. HMAC-SHA256 est le choix standard, et toutes ces lignes affichent la même valeur :
// Node.js
crypto.createHmac('sha256', 'secret').update('hello').digest('hex')
# Python
hmac.new(b'secret', b'hello', hashlib.sha256).hexdigest()
// PHP
hash_hmac('sha256', 'hello', 'secret')
// 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b
Comparez les HMAC avec une fonction à temps constant comme crypto.timingSafeEqual, hmac.compare_digest ou hash_equals, et non avec ==.
Calculer un hash en ligne de commande et dans le code
# Linux (coreutils)
md5sum file.iso
sha1sum file.iso
sha256sum file.iso
# macOS
md5 file.iso
shasum -a 1 file.iso
shasum -a 256 file.iso
# Windows PowerShell
Get-FileHash file.iso -Algorithm MD5
Get-FileHash file.iso -Algorithm SHA1
Get-FileHash file.iso # SHA256 is the default
# Any system with OpenSSL
openssl dgst -sha256 file.iso
# Hashing a string: printf adds no newline, echo does
printf '%s' hello | sha256sum # 2cf24dba5fb0a30e...
echo hello | sha256sum # 5891b5b522d5df08...
Dans le navigateur, crypto.subtle.digest() prend en charge SHA-1, SHA-256, SHA-384 et SHA-512, mais pas MD5 : lui demander MD5 lève une NotSupportedError. C'est pourquoi les outils qui tournent dans le navigateur, y compris ceux de ce site, calculent MD5 avec une implémentation JavaScript distincte.