Fonctions de dérivation de clés : PBKDF2, Argon2 et scrypt comparés
Comparez les fonctions de dérivation de clés pour le chiffrement par mot de passe. Forces et compromis de PBKDF2, Argon2 et scrypt.
Pour les clés de chiffrement dérivées d'un mot de passe en 2026, Argon2id est le choix recommandé (vainqueur du PHC, favori d'OWASP, activement défendu contre les attaquants GPU et ASIC), scrypt est un solide deuxième (résistant à la mémoire, largement déployé dans les cryptomonnaies), et PBKDF2-SHA-256 à 600 000+ itérations reste acceptable pour la compatibilité mais offre une résistance minimale aux GPU. Pour les applications de transfert de fichiers où les utilisateurs saisissent un mot de passe pour protéger un fichier partagé, Argon2id avec 3 itérations, 64 Mio de mémoire et 4 de parallélisme est la référence moderne. PBKDF2 survit parce qu'il est intégré à l'API Web Crypto et ne nécessite aucune dépendance WASM. Voici comment les trois diffèrent et quand chacun a du sens.
Tableau comparatif
| Propriété | PBKDF2 | scrypt | Argon2id | |---|---|---|---| | Année d'introduction | 2000 (RFC 2898) | 2009 (RFC 7914) | 2015 (vainqueur PHC) | | Résistance mémoire | Non | Oui | Oui | | Flexibilité des paramètres | Itérations seulement | N, r, p | temps, mémoire, parallélisme | | Résistance GPU | Faible | Modérée | Forte | | Résistance ASIC | Très faible | Modérée | Forte | | Natif navigateur (Web Crypto) | Oui | Non | Non | | Recommandation OWASP 2024 | Solution de repli acceptable | Acceptable | Préféré | | Coût navigateur typique (matériel moderne) | 600 000 it. = ~500 ms | N=2^17 = ~800 ms | 3 it., 64 Mio = ~1 s |
Pourquoi la résistance mémoire compte
Le modèle de menace pour le chiffrement basé sur mot de passe est la force brute hors ligne. Un attaquant récupère le texte chiffré plus le sel, parcourt un dictionnaire de mots de passe, et essaie de dériver une clé qui déchiffre avec succès. La défense consiste à rendre chaque tentative coûteuse.
PBKDF2 rend chaque tentative coûteuse uniquement en temps CPU (itérations SHA-256). Les GPU modernes exécutent des milliards d'opérations SHA-256 par seconde ; un GPU de gaming peut tester 10 à 100 millions de suppositions PBKDF2-SHA-256-600000 par jour. Les attaquants ASIC font des ordres de grandeur mieux.
Les fonctions résistantes à la mémoire (scrypt, Argon2) nécessitent une quantité fixe de mémoire par tentative. Les GPU et les ASIC ont une bande passante mémoire limitée, donc le parallélisme par appareil est borné. Une exigence de 64 Mio de mémoire signifie qu'un GPU avec 16 Go de VRAM peut exécuter au maximum 256 suppositions parallèles, pas des millions. Le coût économique de la force brute augmente de 2 à 3 ordres de grandeur.
PBKDF2 : le standard historique
PBKDF2 (RFC 2898) itère une fonction pseudo-aléatoire, typiquement HMAC-SHA-256 ou HMAC-SHA-512, sur le mot de passe et le sel. Le nombre d'itérations est le seul paramètre ajustable.
const passwordKey = await crypto.subtle.importKey(
"raw", new TextEncoder().encode(password),
"PBKDF2", false, ["deriveKey"]
);
const aesKey = await crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt, // 16 octets aléatoires
iterations: 600000,
hash: "SHA-256",
},
passwordKey,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
OWASP 2023 recommande au minimum 600 000 itérations de PBKDF2-SHA-256. NIST SP 800-132 est plus ancien et moins spécifique. Certaines specs (par ex. le défaut de LastPass de 2018 à 100 100) sont considérées comme trop faibles en 2026.
Avantages : intégré à Web Crypto, pas de WASM, validé FIPS, fonctionne de manière identique dans Node et les navigateurs.
Limites : aucune résistance mémoire, vulnérable à l'accélération GPU et ASIC. Doubler les itérations double le coût pour l'attaquant mais aussi pour l'utilisateur légitime. À un moment, les utilisateurs légitimes refusent d'attendre et on plafonne les itérations.
scrypt : le premier déploiement résistant à la mémoire
scrypt (RFC 7914) a été inventé par Colin Percival en 2009 pour Tarsnap. Il mélange le matériel du mot de passe à travers un grand buffer mémoire, forçant l'attaquant à détenir ce buffer pendant chaque tentative.
Trois paramètres :
- N : facteur de coût (typiquement 2^14 à 2^20). L'utilisation mémoire est approximativement 128 * N * r octets.
- r : taille de bloc (typiquement 8). Affecte la mémoire et le nombre d'itérations GHASH.
- p : parallélisation (typiquement 1). Des valeurs plus élevées accélèrent le calcul légitime mais aussi les attaquants ; laissez généralement à 1.
OWASP recommande N=2^17, r=8, p=1 comme référence, ce qui consomme ~128 Mio et tourne en environ 800 ms sur du matériel moderne.
scrypt n'est pas dans l'API Web Crypto. En JavaScript, utilisez scrypt-js, @noble/hashes ou libsodium.js. Litecoin et Dogecoin utilisent scrypt comme preuve de travail, ce qui a incité le développement d'ASIC spécifiquement pour scrypt, érodant quelque peu son avantage asymétrique original contre les ASIC.
Argon2id : la référence pour 2026
Argon2 a remporté le Password Hashing Competition en 2015. Trois variantes : Argon2d (la plus rapide, dépendante des données, vulnérable aux canaux auxiliaires), Argon2i (indépendante des données, plus lente), Argon2id (hybride, recommandée dans la plupart des cas). La RFC 9106 l'a standardisée en 2021.
Trois paramètres :
- t (temps) : itérations à travers la mémoire. Typiquement 2-3.
- m (mémoire) : mémoire en Kio. Typiquement 65536 (64 Mio) ou plus.
- p (parallélisme) : degré de parallélisme. Typiquement 1-4.
Référence OWASP 2024 : t=2, m=19456 (19 Mio), p=1 pour un minimum, et t=3, m=65536 (64 Mio), p=4 pour une protection plus forte.
import { argon2id } from '@noble/hashes/argon2';
import { utf8ToBytes } from '@noble/hashes/utils';
const derivedKey = argon2id(utf8ToBytes(password), salt, {
t: 3, m: 65536, p: 4, dkLen: 32
});
Ou via argon2-browser (WASM) :
import argon2 from 'argon2-browser';
const hash = await argon2.hash({
pass: password, salt,
type: argon2.ArgonType.Argon2id,
time: 3, mem: 65536, parallelism: 4, hashLen: 32
});
Argon2id défait les attaquants GPU plus efficacement que scrypt car son schéma d'accès mémoire est moins adapté aux conceptions de mémoire en vrac. Des ASIC pour Argon2 existent en recherche mais ne sont pas encore déployés économiquement à l'échelle des attaquants.
Choisir les paramètres pour votre application
La méthode de calibration : choisissez le délai d'attente le plus long que vos utilisateurs tolèrent (généralement 500 ms à 2 secondes), mesurez sur l'appareil cible le plus lent, et définissez les paramètres pour atteindre ce budget.
Pour les partages de fichiers protégés par mot de passe de type HexaTransfer, où la dérivation se produit une fois lors du téléversement et une fois lors du téléchargement, 1 à 2 secondes est acceptable. Paramètres :
- PBKDF2-SHA-256 : 600 000 à 1 200 000 itérations
- scrypt : N=2^17, r=8, p=1
- Argon2id : t=3, m=65536, p=4
Pour les systèmes de connexion où l'utilisateur attend après avoir saisi son mot de passe, 300 à 500 ms est le plafond UX. Les paramètres se réduisent approximativement de moitié. Pour les scénarios par lot où l'utilisateur n'attend pas (par ex. re-chiffrement en arrière-plan), augmentez à 3 à 5 secondes.
Gestion des sels
Les trois KDF nécessitent un sel. Règles :
- 16 octets aléatoires minimum
- Généré via
crypto.getRandomValues(), jamaisMath.random() - Unique par mot de passe (si deux utilisateurs ont le même mot de passe, leurs sels devraient différer pour que les clés dérivées diffèrent)
- Pas secret — stockez-le avec le texte chiffré
Le poivre (un secret ajouté à toutes les dérivations) est parfois évoqué. Pour le transfert de fichiers où le « serveur » est un simple stockage de blobs, le poivre n'apporte aucune valeur car il n'y a pas de secret côté serveur. Pour les systèmes basés sur des comptes, un poivre côté serveur stocké séparément de la base de données de mots de passe rend les dumps de base de données moins utiles aux attaquants.
Migrer entre KDF
Si vous avez un déploiement existant sur PBKDF2 et souhaitez passer à Argon2id :
- Stockez l'identifiant KDF dans les métadonnées du texte chiffré (
"kdf": "pbkdf2-sha256-600000"ou"kdf": "argon2id-3-65536-4") - Pour les nouveaux téléversements, utilisez Argon2id
- Lors du déchiffrement, lisez l'identifiant KDF et utilisez la fonction correspondante
- Ne mettez jamais à jour aveuglément les anciens textes chiffrés ; vous auriez besoin du mot de passe pour re-dériver
LastPass, 1Password et Bitwarden ont tous traversé cette migration. Tous trois utilisent désormais par défaut PBKDF2 à 600 000+ itérations, avec Argon2id disponible dans les versions plus récentes.
Et bcrypt ?
bcrypt (1999) est une bonne fonction de hachage de mots de passe avec une légère résistance mémoire. Elle plafonne les entrées à 72 octets (un piège célèbre — les longs mots de passe sont tronqués silencieusement avant les tours 2011). C'est l'ancienne valeur par défaut dans Ruby on Rails et de nombreux frameworks PHP. Pour du nouveau code en 2026, préférez Argon2id ; bcrypt est correct pour maintenir des systèmes existants.
La recommandation réaliste
Pour un nouveau service de transfert de fichiers en 2026 :
- Si vous pouvez livrer une dépendance de 15 à 200 Ko : Argon2id via @noble/hashes ou libsodium.js
- Si vous avez besoin de zéro dépendance avec une taille de bundle minimale : PBKDF2-SHA-256 à 600 000 itérations via Web Crypto
- Si vous écrivez un portefeuille de cryptomonnaies ou quelque chose héritant de scrypt : scrypt à N=2^17
Pour les applications de production gérant des fichiers sensibles, Argon2id vaut la dépendance WASM. Pour les partages simples protégés par mot de passe où les utilisateurs génèrent de toute façon un mot de passe aléatoire, PBKDF2 est adéquat car l'entropie est dans le mot de passe, pas dans le KDF.
Essayez sur hexatransfer.com — gratuit, sans compte, jusqu'à 10 Go.
Envoyez vos fichiers volumineux en toute sécurité avec le chiffrement de bout en bout
Transférez des fichiers jusqu'à 10 Go gratuitement avec le chiffrement de bout en bout. Aucun compte requis. Vos fichiers sont chiffrés dans votre navigateur avant l'envoi — personne d'autre ne peut les lire.
Envoyer un fichier