OWASP & AppSec

Erreurs fréquentes en crypto côté développeur : top 12 à éviter

Top 12 des erreurs crypto côté développeur 2026 : hash mdp faible, ECB, IV reuse, alg:none JWT, ECDSA nonce, padding oracle, secrets hardcodés, timing, TLS faible.

Naim Aouaichia
13 min de lecture
  • Cryptographie
  • Secure coding
  • OWASP A02
  • JWT
  • AES
  • Password hashing
  • TLS
  • DevSecOps

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 False

Algorithmes acceptés en 2026

AlgorithmeRecommandation OWASP 2025Tuning
Argon2idPréférém=64MB, t=3, p=4
scryptAcceptableN=2^17, r=8, p=1
bcryptAcceptablecost=12+
PBKDF2-HMAC-SHA-256Si contrainte FIPSiterations=600 000+
SHA-256 / MD5 directBANNIRn/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] ensemble

Erreur 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 reuse

Exemple 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    : BCryptGenRandom

Erreur 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 configs

Erreur 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/secrets

Parade : 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 trait

Erreur 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 ciphers

Erreur 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-time

Erreur 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éfaut

Erreur 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ée

Erreur 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

#ErreurImpactParade recommandée
1Hash mdp MD5/SHA-256 directCracking massif offlineArgon2id, bcrypt, scrypt, PBKDF2
2AES en mode ECBPatterns visibles, data leakAES-GCM, ChaCha20-Poly1305
3IV / nonce réutiliséKeystream leak, forgeRandom 96 bits, AES-GCM-SIV, XChaCha20
4RNG faible (Math.random)Tokens prévisiblescrypto.randomBytes, secrets module
5JWT alg:none ou confusionBypass authalgorithms=["RS256"] strict
6Secrets hardcodésFuite massiveVault, KMS, OIDC Workload Identity
7Comparaison non-constant-timeTiming attacktimingSafeEqual, compare_digest
8TLS faible ou verify=FalseMitMMozilla Intermediate, pinning mobile
9Padding Oracle AES-CBCPlaintext recoveryAEAD (GCM, ChaCha20-Poly1305)
10ECDSA nonce réutiliséExtraction clé privéeEdDSA, RFC 6979 déterministe
11Downgrade attacks autorisésFREAK, POODLE, BEASTDésactiver protocoles/ciphers faibles
12Rolling your own cryptoToutes les failles ci-dessuslibsodium, 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 RNG

Scanners 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-ciphers

Scanners secrets

gitleaks, trufflehog, GitGuardian, Snyk Secrets
GitHub Secret Scanning + Push Protection (natif)

Bonnes pratiques transverses 2026

  1. Ne jamais implémenter la crypto soi-même. Utiliser libsodium, Tink, Web Crypto, cryptography pyca, BouncyCastle, ring.
  2. Préférer les APIs haut niveau : sealed_box libsodium plutôt que composer AES + RSA, Fernet plutôt que AES-CBC+HMAC manuel.
  3. Audits SAST crypto dans chaque PR : Semgrep, CodeQL, gosec, Bandit.
  4. Secrets hors du code : KMS, Vault, OIDC Workload Identity. Jamais en .env commit.
  5. Rotation automatisée des clés et certificats via cert-manager, AWS ACM, Let's Encrypt.
  6. Monitoring des endpoints TLS public via testssl.sh, SSL Labs cron hebdomadaire.
  7. Logs d'audit crypto : KMS access logs, JWT validation failures, TLS handshake failures.
  8. Formation continue : OWASP Top 10 Cryptographic Failures + cryptopals challenges pour les AppSec.
  9. Pentest dédié crypto annuel sur les produits à fort enjeu (fintech, santé, defense).
  10. 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.

Questions fréquentes

  • Pourquoi les développeurs font-ils autant d'erreurs en crypto ?
    Trois raisons structurelles. La crypto est un domaine spécialisé où l'intuition est souvent trompeuse (par exemple : un algorithme mathématiquement robuste peut être rendu non sécurisé par un mauvais mode opératoire). La documentation des bibliothèques est parfois incomplète, ambiguë, ou ne met pas en avant les pièges. Et la plupart des formations dev n'abordent pas la crypto en profondeur. OWASP A02 Cryptographic Failures reste dans le top 2 du Top 10 depuis 2021, confirmant la persistance du problème.
  • Quelle est l'erreur crypto la plus fréquente en 2026 ?
    Le hash de mot de passe avec SHA-256 direct (ou MD5, SHA-1) sans salt ni function adaptive. Sur des GPU 2026, un attaquant teste des milliards de hashes SHA-256 par seconde - cracking massif d'une base leakée. La parade est connue depuis 2013 : utiliser Argon2id (recommandé OWASP 2025), bcrypt (cost factor 12+), scrypt ou PBKDF2. Pourtant les audits révèlent encore des applications 2025 qui hashent avec SHA-256 ou MD5. C'est statistiquement l'erreur #1.
  • Dois-je coder ma propre crypto ?
    Non, jamais. La règle « don't roll your own crypto » est citée par tous les cryptographes depuis 20 ans. Les primitives correctement implémentées sont subtiles (constant-time, validation de point, padding resistant) et les erreurs souvent invisibles en test mais critiques en production. Utiliser des bibliothèques auditées : libsodium, Tink (Google), Web Crypto API, cryptography (Python pyca), BouncyCastle (Java), ring (Rust), OpenSSL 3+. Pour les protocoles : Noise Protocol Framework, TLS 1.3, Signal Protocol. Implémenter soi-même = garantie de vulnérabilité.
  • Qu'est-ce qu'une attaque de timing et comment l'éviter ?
    Une attaque de timing exploite le fait que le temps d'exécution d'une comparaison ou opération peut leaker des informations sur les bytes secrets. Classique : `if password == user_input` qui compare byte par byte et s'arrête au premier diff - en mesurant le temps, un attaquant devine byte par byte. Parade : utiliser des fonctions de comparaison constant-time (`crypto.timingSafeEqual` Node, `hmac.compare_digest` Python, `ConstantTimeAreEqual` Java). Similaire pour les opérations cryptographiques : les bibliothèques modernes (libsodium, ring) sont constant-time par construction.
  • ECB, CBC, GCM : quel mode AES utiliser en 2026 ?
    AES-GCM (ou AES-GCM-SIV pour IV reuse resistance) est le standard moderne. Il fournit chiffrement authentifié (AEAD) : chiffrement + authentification en une opération. Jamais utiliser ECB (patterns visibles, historique pingouin Tux), CBC sans authentification (padding oracle), CTR sans MAC (tampering possible). Alternative : ChaCha20-Poly1305 (RFC 8439) souvent plus rapide sur hardware sans AES-NI. Pour des cas très particuliers : XChaCha20-Poly1305 (nonce étendu 24 octets) ou AES-GCM-SIV (RFC 8452, résistant IV reuse).
  • Puis-je utiliser MD5 ou SHA-1 en 2026 ?
    MD5 et SHA-1 sont cassés pour tout usage de sécurité depuis 2004 (MD5 collision) et 2017 (SHAttered SHA-1). À proscrire pour : hash de mot de passe, signatures, MAC, intégrité de fichier de sécurité. Usages non-sécurité acceptables mais déconseillés : fingerprint de cache, hash non-adversarial. Préférer SHA-256, SHA-3, BLAKE2, BLAKE3 pour tous les nouveaux usages. Beaucoup d'outils legacy utilisent encore MD5 (Git commit hashes, certains protocoles UUID) - acceptable uniquement si l'objectif n'est pas la sécurité.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.