Les erreurs cryptographiques côté développeur figurent dans le top 2 du OWASP Top 10 depuis 2021 (A02 Cryptographic Failures, reconduite en 2025) et concernent la majorité des applications auditées en pentest. Ces erreurs sont particulièrement coûteuses : contrairement à une faille logique qui peut être patchée rapidement, un choix crypto faible (hash mdp en SHA-256, chiffrement ECB, JWT alg:none) compromet souvent historiquement toutes les données chiffrées depuis le début du système. Les 12 erreurs les plus fréquentes en 2026 couvrent cinq catégories : hash de mot de passe faible, usage incorrect de modes de chiffrement, randomness cryptographique défaillante, implémentations vulnérables (JWT, TLS, signatures), et mauvaise gestion des secrets. La règle transversale qui évite 90 % de ces erreurs reste inchangée depuis 20 ans : ne jamais implémenter la crypto soi-même, toujours utiliser des bibliothèques auditées (libsodium, Tink, Web Crypto, cryptography pyca, BouncyCastle, ring). Cet article détaille chaque erreur avec code vulnérable vs corrigé, les CVE associées, les bonnes pratiques et les outils de détection SAST.
Contexte OWASP A02 Cryptographic Failures
A02 en 2021 (promu au rang #2 depuis #3 A3:2017 Sensitive Data Exposure), reconduite A04 dans le draft 2025 au même niveau de criticité. Couvre les failures liées à :
- Transmission de données sensibles en clair (HTTP vs HTTPS).
- Usage d'algorithmes faibles ou obsolètes.
- Mauvaise gestion des clés cryptographiques.
- Implémentations incorrectes (IV reuse, padding oracle, timing).
- Validation insuffisante (JWT, certificats).
Impact typique : fuite de bases de données avec mots de passe crackés en heures, bypass d'authentification, signature forgée, MitM possible.
Erreur 1 - Hash de mot de passe avec SHA-256/MD5 direct
La vulnérabilité la plus répandue. Un hash rapide comme SHA-256 ou MD5 est optimisé pour la vitesse - exactement ce qu'un attaquant souhaite pour cracker massivement. Sur un GPU 2026, un attaquant teste 10-100 milliards de hashes SHA-256 par seconde.
# VULNÉRABLE
import hashlib
def hash_password(password: str) -> str:
return hashlib.sha256(password.encode()).hexdigest()
# Sur GPU RTX 4090 : 20 Ghash/s. Base de 100k mdp moyens crackée en heures.# CORRIGÉ - Argon2id recommandé OWASP 2025
from argon2 import PasswordHasher
ph = PasswordHasher(
time_cost=3, # itérations
memory_cost=65536, # 64 MB
parallelism=4,
)
def hash_password(password: str) -> str:
return ph.hash(password)
def verify_password(stored_hash: str, password: str) -> bool:
try:
ph.verify(stored_hash, password)
return True
except Exception:
return FalseAlgorithmes acceptés en 2026
| Algorithme | Recommandation OWASP 2025 | Tuning |
|---|---|---|
| Argon2id | Préféré | m=64MB, t=3, p=4 |
| scrypt | Acceptable | N=2^17, r=8, p=1 |
| bcrypt | Acceptable | cost=12+ |
| PBKDF2-HMAC-SHA-256 | Si contrainte FIPS | iterations=600 000+ |
| SHA-256 / MD5 direct | BANNIR | n/a |
Erreur 2 - AES en mode ECB
ECB (Electronic Code Book) chiffre chaque bloc indépendamment. Deux blocs identiques produisent le même chiffré - les patterns sont visibles à l'œil nu. Cas d'école : le pingouin Tux chiffré ECB reste reconnaissable.
# VULNÉRABLE - ECB
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
cipher = Cipher(algorithms.AES(key), modes.ECB()) # JAMAIS ECB
# CORRIGÉ - GCM (AEAD authentifié)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
aesgcm = AESGCM(key)
nonce = os.urandom(12) # 96 bits - standard GCM
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data=b"ctx-v1")
# Stocker [nonce, ciphertext] ensembleErreur 3 - IV / nonce réutilisé
Un IV (AES-CBC) ou nonce (AES-GCM, ChaCha20) doit être unique par chiffrement avec une clé donnée. Sa réutilisation casse totalement la sécurité.
AES-GCM avec nonce reuse = catastrophe :
- Récupération du stream keystream
- Forge de ciphertext arbitraire
- Authentication bypass
Moyens d'assurer l'unicité :
Random 96 bits (AES-GCM standard) : OK si RNG crypto sûr
Compteur atomique persistant : OK si jamais réinitialisé
XChaCha20-Poly1305 (24 octets random) : OK même sous contention
AES-GCM-SIV (RFC 8452) : résistant nonce reuseExemple historique : PS3 encryption
Sony PS3 utilisait un nonce fixe pour signer les mises à jour - extraction de clé privée par fail0verflow 2010. Le même type de faiblesse appliqué au chiffrement AES-GCM produit un disaster équivalent.
Erreur 4 - RNG faible (Math.random, rand)
Utiliser un générateur non-cryptographique pour produire des clés, tokens, nonces.
// VULNÉRABLE
function generateToken() {
return Math.random().toString(36).substr(2); // PRÉVISIBLE
}
// CORRIGÉ (Node.js)
const crypto = require('crypto');
function generateToken() {
return crypto.randomBytes(32).toString('base64url');
}
// CORRIGÉ (navigateur)
function generateToken() {
const arr = new Uint8Array(32);
crypto.getRandomValues(arr);
return btoa(String.fromCharCode(...arr));
}Sources d'aléa acceptables
Navigateur : crypto.getRandomValues()
Node.js : crypto.randomBytes(), crypto.randomUUID()
Python : secrets module (pas random!), os.urandom()
Java : SecureRandom (jamais Random)
Go : crypto/rand (jamais math/rand pour sécurité)
Linux : /dev/urandom, getrandom(2)
Windows : BCryptGenRandomErreur 5 - JWT alg:none ou confusion HS256/RS256
Trois vulnérabilités JWT classiques documentées depuis 2015.
alg:none
Attaque : header { "alg": "none" } + signature vide.
Si le validateur accepte "none", tout token forgé passe.
Parade : whitelister explicitement les algorithmes.Confusion HS256/RS256
# VULNÉRABLE - on accepte l'algo du header
import jwt
payload = jwt.decode(token, key, algorithms=None) # JAMAIS
# Attaquant peut signer HS256 avec la clé publique RS256 comme secret HMAC
# CORRIGÉ - algorithme whitelisté
payload = jwt.decode(token, public_key, algorithms=["RS256"])Clé trop faible pour HS256
HS256 symétrique avec un secret court et devinable (ex. "mysecret") - crackable par brute force offline.
Règles 2026 :
Si HS256 : secret >= 256 bits d'entropie (32 octets random)
Préférer RS256 ou ES256 pour éviter la symétrie
JWT alg:none interdit dans TOUTES les configsErreur 6 - Secrets hardcodés ou en .env commit
Fréquence : 1ère cause de compromission cloud en 2024-2025
(GitGuardian, Snyk, Mandiant)
Outils de détection SAST/CI 2026 :
gitleaks (OSS)
trufflehog (OSS)
GitHub Secret Scanning + Push Protection (natif, gratuit public)
Snyk secrets
Semgrep p/secretsParade : injection runtime uniquement
# VULNÉRABLE
export DATABASE_PASSWORD="p@ssw0rd123" # commit dans .env
# CORRIGÉ
# Vault, AWS Secrets Manager, GCP Secret Manager injecté à l'exécution
# OIDC Workload Identity Federation pour CI/CD (sans secret long-durée)Voir gestion des clés : les bases du key management en 2026.
Erreur 7 - Comparaison non-constant-time
Comparer un hash/token/signature byte par byte avec == leak l'information de correspondance partielle via timing.
// VULNÉRABLE
function checkToken(userToken, validToken) {
return userToken === validToken; // timing attack possible
}
// CORRIGÉ (Node.js)
const crypto = require('crypto');
function checkToken(userToken, validToken) {
const a = Buffer.from(userToken);
const b = Buffer.from(validToken);
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}Équivalents par langage
Node.js : crypto.timingSafeEqual(a, b)
Python : hmac.compare_digest(a, b)
Java : MessageDigest.isEqual(a, b) depuis JDK 6u17
Go : subtle.ConstantTimeCompare(a, b)
Ruby : ActiveSupport::SecurityUtils.secure_compare
Rust : subtle crate, CtEq traitErreur 8 - TLS mal configuré
Déploiement TLS avec ciphers faibles, protocole obsolète, certificat invalide non détecté.
Configuration TLS 2026 acceptable (Mozilla Intermediate) :
Protocoles : TLS 1.2 + TLS 1.3 uniquement
Ciphers TLS 1.3 : toutes les suites standard acceptables
Ciphers TLS 1.2 : ECDHE-RSA-AES-GCM, ECDHE-ECDSA-AES-GCM,
ECDHE-CHACHA20-POLY1305
HSTS activé avec preload
OCSP stapling
Certificates ECDSA P-256 ou RSA 2048+
À bannir : TLS 1.0, 1.1, SSLv3, RC4, 3DES, EXPORT ciphers, NULL ciphersErreur courante : désactiver la vérification du certificat
# VULNÉRABLE
import requests
requests.get('https://api.example.com', verify=False) # JAMAIS en prod
# CORRIGÉ
requests.get('https://api.example.com', verify=True)
# Si certificat auto-signé : verify='/path/to/ca-bundle.crt'Pinning en mobile
Pour les apps mobile manipulant des données sensibles (banque, santé) : certificate pinning obligatoire. TrustKit (iOS), Network Security Config (Android), OkHttp CertificatePinner.
Erreur 9 - Padding Oracle (AES-CBC sans MAC)
Si vous utilisez AES-CBC sans MAC, un attaquant peut récupérer le plaintext byte par byte en observant les erreurs de padding côté serveur. Historique : POODLE attack (2014).
Parade 2026 :
Toujours utiliser AEAD (Authenticated Encryption with Associated Data) :
AES-GCM (standard)
ChaCha20-Poly1305 (RFC 8439)
AES-CCM (contextes IoT)
XChaCha20-Poly1305
Si CBC obligatoire (legacy) : encrypt-then-MAC avec HMAC-SHA-256 constant-timeErreur 10 - ECDSA avec nonce prévisible
ECDSA requiert un nonce k unique et cryptographiquement aléatoire par signature. Un k réutilisé ou prévisible expose directement la clé privée.
Incidents historiques :
Sony PS3 (2010) : k fixe → clé extraite
Android Bitcoin (2013) : SecureRandom mal initialisé → wallets vidés
Parade 2026 :
Déterministic ECDSA (RFC 6979) : k dérivé de hash(message + privateKey)
EdDSA / Ed25519 (RFC 8032) : déterministe par design
Bibliothèques à jour : toutes implémentent RFC 6979 par défautErreur 11 - Downgrade attacks non bloqués
Un attaquant force la négociation vers un algorithme faible. Classiques : FREAK (TLS export), Logjam (DH 512 bits), BEAST (CBC), POODLE (SSL 3.0).
Parade 2026 :
Désactiver tous les protocoles et ciphers faibles côté serveur ET client
TLS_FALLBACK_SCSV activé sur clients compatibles
Monitoring SSL Labs / testssl.sh sur endpoints publics
Pas d'acceptation de « legacy clients » sans analyse de risque documentéeErreur 12 - Rolling your own crypto
La mère de toutes les erreurs. Implémenter soi-même AES, RSA, ECDH, ou un protocole complet. Même les experts font des erreurs subtiles.
Exemples de « maison » qui ont mal tourné :
Telegram MTProto 1.0 : corrections après plusieurs audits
WhatsApp protocole custom : remplacé par Signal Protocol
Projets blockchain maison : souvent vulnérables dans les 6 premiers mois
Custom SAML validator : XSW partout
Custom session cookie crypto: timing, padding oracle, key reuse
Règle universelle :
Composer des primitives auditées via une bibliothèque haut niveau.
libsodium + Tink couvrent 99 % des besoins applicatifs modernes.Tableau récapitulatif des 12 erreurs
| # | Erreur | Impact | Parade recommandée |
|---|---|---|---|
| 1 | Hash mdp MD5/SHA-256 direct | Cracking massif offline | Argon2id, bcrypt, scrypt, PBKDF2 |
| 2 | AES en mode ECB | Patterns visibles, data leak | AES-GCM, ChaCha20-Poly1305 |
| 3 | IV / nonce réutilisé | Keystream leak, forge | Random 96 bits, AES-GCM-SIV, XChaCha20 |
| 4 | RNG faible (Math.random) | Tokens prévisibles | crypto.randomBytes, secrets module |
| 5 | JWT alg:none ou confusion | Bypass auth | algorithms=["RS256"] strict |
| 6 | Secrets hardcodés | Fuite massive | Vault, KMS, OIDC Workload Identity |
| 7 | Comparaison non-constant-time | Timing attack | timingSafeEqual, compare_digest |
| 8 | TLS faible ou verify=False | MitM | Mozilla Intermediate, pinning mobile |
| 9 | Padding Oracle AES-CBC | Plaintext recovery | AEAD (GCM, ChaCha20-Poly1305) |
| 10 | ECDSA nonce réutilisé | Extraction clé privée | EdDSA, RFC 6979 déterministe |
| 11 | Downgrade attacks autorisés | FREAK, POODLE, BEAST | Désactiver protocoles/ciphers faibles |
| 12 | Rolling your own crypto | Toutes les failles ci-dessus | libsodium, Tink, bibliothèques éprouvées |
Outils de détection pour les équipes
SAST orientés crypto
Semgrep
Rules p/owasp-top-ten et p/security-audit
Détection JWT.decode sans algorithms, bcrypt missing, etc.
CodeQL
Queries CWE-327 (Use of broken cryptographic algorithm)
Queries CWE-328 (Reversible one-way hash)
Queries CWE-330 (Use of insufficiently random values)
Bandit (Python)
B301-B505 : hashlib.md5, ECB mode, random, SSL verify
gosec (Go)
G401 : weak cryptographic primitives
G501-G505 : MD5, SHA1, DES, RC4, CTR
Snyk Code
Couverture large crypto misuse par langage
SonarQube
Rules crypto : hash weak, IV reuse, weak RNGScanners TLS
testssl.sh (OSS) : analyse CLI complète d'un endpoint
SSL Labs SSL Test : note A+ à F, rapport détaillé
Mozilla Observatory : audit TLS + headers
hardenize.com : audit complet stack web
nmap --script=ssl-enum-ciphersScanners secrets
gitleaks, trufflehog, GitGuardian, Snyk Secrets
GitHub Secret Scanning + Push Protection (natif)Bonnes pratiques transverses 2026
- Ne jamais implémenter la crypto soi-même. Utiliser libsodium, Tink, Web Crypto, cryptography pyca, BouncyCastle, ring.
- Préférer les APIs haut niveau :
sealed_boxlibsodium plutôt que composer AES + RSA, Fernet plutôt que AES-CBC+HMAC manuel. - Audits SAST crypto dans chaque PR : Semgrep, CodeQL, gosec, Bandit.
- Secrets hors du code : KMS, Vault, OIDC Workload Identity. Jamais en .env commit.
- Rotation automatisée des clés et certificats via cert-manager, AWS ACM, Let's Encrypt.
- Monitoring des endpoints TLS public via testssl.sh, SSL Labs cron hebdomadaire.
- Logs d'audit crypto : KMS access logs, JWT validation failures, TLS handshake failures.
- Formation continue : OWASP Top 10 Cryptographic Failures + cryptopals challenges pour les AppSec.
- Pentest dédié crypto annuel sur les produits à fort enjeu (fintech, santé, defense).
- Revue des algorithmes tous les 2-3 ans : SHA-1 déprécié en 2017, MD5 depuis 2012, roadmap post-quantique en cours.
Points clés à retenir
- 12 erreurs crypto développeur récurrentes en 2026, compilées depuis OWASP A02 Cryptographic Failures (top 2 depuis 2021) : hash mdp faible, ECB mode, IV reuse, RNG faible, JWT alg:none, secrets hardcodés, comparaison non-constant-time, TLS faible, padding oracle, ECDSA nonce, downgrade attacks, rolling your own.
- Règle transverse qui évite 90 % des erreurs : ne jamais implémenter la crypto soi-même. Utiliser libsodium, Tink, cryptography (Python), BouncyCastle (Java), ring (Rust), Web Crypto API.
- Hash mot de passe 2026 : Argon2id (recommandé OWASP 2025), bcrypt cost=12+, scrypt, PBKDF2-HMAC-SHA-256 avec 600k+ itérations. Bannir MD5, SHA-1, SHA-256 direct.
- Chiffrement symétrique 2026 : AES-GCM (AEAD), ChaCha20-Poly1305, XChaCha20-Poly1305, AES-GCM-SIV pour IV reuse resistance. Bannir ECB, CBC sans MAC.
- JWT : whitelister algorithms=["RS256"] ou ["ES256"] strict, bannir
alg:none, valider toutes les claims (iss, aud, exp, nonce), HS256 uniquement si secret 256+ bits. - Secrets : jamais en code ni .env commit. Vault/KMS en production, OIDC Workload Identity Federation pour CI/CD.
- Outils gratuits à activer : Semgrep ruleset OWASP, gitleaks/Push Protection, testssl.sh cron, Dependabot. Couvrent 80 % des détections automatiques.
Pour comprendre les algorithmes modernes à utiliser en crypto, voir ECC expliqué : cryptographie sur courbes elliptiques 2026. Pour gérer correctement les clés mentionnées dans cet article, lire gestion des clés : les bases du key management en 2026. Pour la validation correcte des JWT OIDC qui évite les erreurs 5 et 7, voir OpenID Connect expliqué : flows, JWT, PKCE, sécurité 2026. Pour un plan de progression AppSec complet incluant la maîtrise crypto, voir la roadmap AppSec Engineer 2026.






