Plateforme de Cryptographie Par Kaci AMAOUCHE

Fonctions de hachage et modes opératoires

Ce chapitre approfondit l'étude des fonctions de hachage cryptographiques et des différents modes opératoires utilisés en cryptographie symétrique. Ces deux éléments sont fondamentaux pour la sécurité des systèmes cryptographiques modernes et sont utilisés dans de nombreuses applications sécurisées.

2.1. Fonctions de hachage cryptographiques avancées

Structure interne des fonctions de hachage modernes

Les fonctions de hachage cryptographiques modernes sont généralement construites selon l'une des trois approches suivantes :

Construction Merkle-Damgård

Utilise une fonction de compression itérative avec chaînage pour transformer un message de taille arbitraire en une empreinte de taille fixe.

Exemples : MD5, SHA-1, SHA-2

IV M₁ f M₂ f Hash
Construction Sponge

Utilise une fonction de permutation avec des phases d'absorption et de pressage, permettant une sortie de taille variable.

Exemples : SHA-3 (Keccak), SHAKE

r c M₁ M₂ Permutation f Z
HAIFA

HAsh Iterative FrAmework, une extension de Merkle-Damgård incluant un compteur de bits et du salage.

Exemples : BLAKE2, BLAKE3

IV M₁ S # f f H

Analyse approfondie des principales fonctions de hachage

Fonction Année Construction Taille de sortie Propriétés notables État de sécurité
MD5 1992 Merkle-Damgård 128 bits Rapide, sortie compacte Cassé Collisions trouvées en 2004
SHA-1 1995 Merkle-Damgård 160 bits Anciennement très utilisé (Git, TLS) Cassé Collision pratique démontrée en 2017
SHA-2 (SHA-256/512) 2001 Merkle-Damgård 256/512 bits Famille de fonctions, résistant aux attaques length-extension Sûr Standard actuel
SHA-3 (Keccak) 2015 Sponge 224/256/384/512 bits Construction fondamentalement différente de SHA-2 Sûr Standard NIST actuel
BLAKE2 2012 HAIFA Variable (jusqu'à 512 bits) Optimisé pour la vitesse, paramétrisation flexible Sûr Alternative rapide à SHA-3
BLAKE3 2020 Merkle + HAIFA Variable (défaut 256 bits) Parallélisable, extrêmement rapide Sûr État de l'art

Fonctionnement interne de SHA-256

SHA-256 est l'une des fonctions de hachage les plus utilisées aujourd'hui. Examinons son fonctionnement interne en détail :

Algorithme SHA-256
  1. Préparation des messages
    • Padding : ajout d'un bit '1' suivi de '0's pour atteindre une longueur de 448 modulo 512 bits
    • Ajout de la longueur originale du message sur 64 bits
    • Division en blocs de 512 bits (16 mots de 32 bits chacun)
  2. Initialisation des valeurs de hachage
    • Huit constantes initiales (dérivées des parties fractionnaires des racines carrées des 8 premiers nombres premiers) :
      h[0] = 0x6a09e667    h[4] = 0x510e527f
      h[1] = 0xbb67ae85    h[5] = 0x9b05688c
      h[2] = 0x3c6ef372    h[6] = 0x1f83d9ab
      h[3] = 0xa54ff53a    h[7] = 0x5be0cd19
  3. Préparation de la table de constantes
    • 64 constantes dérivées des parties fractionnaires des racines cubiques des 64 premiers nombres premiers
  4. Traitement des blocs
    • Extension du bloc en 64 mots de 32 bits
    • Application de la fonction de compression principale
    • Mise à jour des valeurs de hachage intermédiaires
  5. Production du digest final
    • Concaténation des huit valeurs de hachage finales h[0]...h[7]
Fonction de compression de SHA-256

Au cœur de SHA-256 se trouvent les fonctions suivantes :

$$Ch(x, y, z) = (x \land y) \oplus (\neg x \land z)$$

$$Maj(x, y, z) = (x \land y) \oplus (x \land z) \oplus (y \land z)$$

$$\Sigma_0(x) = ROTR^2(x) \oplus ROTR^{13}(x) \oplus ROTR^{22}(x)$$

$$\Sigma_1(x) = ROTR^6(x) \oplus ROTR^{11}(x) \oplus ROTR^{25}(x)$$

où \(ROTR^n(x)\) représente la rotation à droite de \(x\) de \(n\) bits.

Boucle principale de compression
// Initialiser les registres de travail
a = h[0]; b = h[1]; c = h[2]; d = h[3];
e = h[4]; f = h[5]; g = h[6]; h = h[7];

// Boucle principale de compression
for (t = 0; t < 64; t++) {
    T1 = h + Σ₁(e) + Ch(e, f, g) + K[t] + W[t];
    T2 = Σ₀(a) + Maj(a, b, c);
    h = g;
    g = f;
    f = e;
    e = d + T1;
    d = c;
    c = b;
    b = a;
    a = T1 + T2;
}

// Mettre à jour les valeurs de hachage
h[0] += a; h[1] += b; h[2] += c; h[3] += d;
h[4] += e; h[5] += f; h[6] += g; h[7] += h;

Construction Sponge et SHA-3

SHA-3 (Keccak) utilise une construction fondamentalement différente appelée "construction éponge" :

Principes de la construction Sponge
  • État interne : Matrice de 5×5 mots de 64 bits (1600 bits au total)
  • Phase d'absorption : Le message est absorbé bloc par bloc en faisant un XOR avec une partie de l'état (la "rate")
  • Phase de pressurage : L'état est "pressé" pour produire le hash final
  • Avantages :
    • Résistance naturelle aux attaques length-extension
    • Sortie de taille arbitraire (XOFs - fonctions de sortie extensible)
    • Construction modulaire et flexible
r (rate) c (capacity) M₁ M₂ Permutation f Z Squeezing
Exemple : Calcul SHA-256 en pseudo-code Python
import hashlib

message = "Hello, World!"
# Encode en UTF-8 et calcule le hash SHA-256
sha256_hash = hashlib.sha256(message.encode('utf-8')).hexdigest()
print(f"SHA-256 de '{message}' : {sha256_hash}")

# Implémentation manuelle des principales étapes (simplifié)
def manual_sha256(message):
    # Initialisation des valeurs de hachage (h0 à h7)
    h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 
         0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
    
    # Préparation du message (padding)
    # ... code de préparation ...
    
    # Traitement pour chaque bloc de 512 bits
    for block in blocks:
        # Expansion du bloc en 64 mots de 32 bits
        w = expand_block(block)
        
        # Initialisation des registres de travail
        a, b, c, d, e, f, g, h_temp = h
        
        # Boucle principale de compression
        for i in range(64):
            # ... fonctions de compression ...
            
        # Mise à jour des valeurs de hachage
        h[0] += a
        h[1] += b
        # ... et ainsi de suite
    
    # Assemblage du digest final
    return ''.join(format(x, '08x') for x in h)

Résultat : dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f

Applications avancées des fonctions de hachage

HMAC (Hash-based Message Authentication Code)

Utilisé pour l'authentification de messages à l'aide d'une fonction de hachage cryptographique et d'une clé secrète.

$$HMAC(K, m) = H((K' \oplus opad) \| H((K' \oplus ipad) \| m))$$

où :

  • \(H\) est la fonction de hachage
  • \(K'\) est la clé dérivée de \(K\)
  • \(opad\) et \(ipad\) sont des constantes
  • \(\|\) représente la concaténation

Applications : TLS, signatures d'API, jetons d'authentification (JWT)

HKDF (HMAC-based Key Derivation Function)

Méthode standardisée pour dériver des clés cryptographiques à partir d'une entrée à faible entropie ou d'un secret partagé.

Comporte deux étapes principales :

  • Extraction : crée une clé pseudoaléatoire (PRK) à partir du matériel source
  • Expansion : génère des clés de sortie déterministes de longueur arbitraire

$$PRK = HMAC(salt, IKM)$$

$$OKM = HMAC(PRK, T(1) \| info) \| HMAC(PRK, T(2) \| info) \| ...$$

Applications : Dérivation de clés dans TLS 1.3, Signal Protocol

Structures de données à base de hachage
Arbre de Merkle

Structure de données arborescente où chaque feuille contient le hash d'un bloc de données, et chaque nœud interne contient le hash de ses enfants.

H H₁ H₂ H₁₁ H₁₂ H₂₁ H₂₂ Bloc 1 Bloc 2 Bloc 3 Bloc 4

Applications : Blockchain, Git, IPFS, certificats transparents

Fonctions à preuve de travail (PoW)

Fonctions de hachage utilisées pour prouver qu'un certain travail computationnel a été effectué. Le défi consiste généralement à trouver une entrée produisant un hash avec un certain nombre de zéros au début.

// Exemple simplifié de preuve de travail 
// (similaire à Bitcoin)
function mineBlock(data, difficulty) {
  let nonce = 0;
  let hash;
  
  // Cible : hash commençant par 'difficulty' zéros
  const target = "0".repeat(difficulty);
  
  while(true) {
    // Concaténer les données avec le nonce
    const attempt = data + nonce.toString();
    
    // Calculer le hash
    hash = sha256(attempt);
    
    // Vérifier si le hash commence par le nombre 
    // requis de zéros
    if(hash.substring(0, difficulty) === target) {
      return { nonce, hash };
    }
    
    nonce++;
  }
}

Applications : Cryptocurrencies, protection contre le spam, mécanismes anti-DoS

2.2. Modes opératoires de chiffrement

Principes fondamentaux des modes opératoires

Les modes opératoires sont des méthodes pour appliquer un algorithme de chiffrement par bloc (comme AES) à des messages de longueur arbitraire. Ils déterminent comment les blocs sont traités et combinés, ce qui affecte directement les propriétés de sécurité du système cryptographique.

Modes opératoires classiques

ECB (Electronic CodeBook)

Chaque bloc est chiffré indépendamment avec la même clé :

$$C_i = E_K(P_i)$$

P₁ P₂ P₃ E E E K K K C₁ C₂ C₃

Avantages : Simple, parallélisable

Inconvénients : Ne cache pas les motifs (les blocs identiques produisent des chiffrés identiques), vulnérable aux attaques par replay

Verdict : Ne jamais utiliser

CBC (Cipher Block Chaining)

Chaque bloc de texte clair est combiné (XOR) avec le bloc chiffré précédent avant d'être chiffré :

$$C_i = E_K(P_i \oplus C_{i-1})$$

$$C_0 = IV$$ (vecteur d'initialisation)

IV P₁ P₂ E E K K C₁ C₂

Avantages : Cache les motifs, un changement dans un bloc se propage à tous les blocs suivants

Inconvénients : Non parallélisable pour le chiffrement, vulnérable aux attaques par padding oracle

Verdict : Utilisable avec précaution

CTR (Counter)

Transforme un chiffrement par bloc en chiffrement à flot en chiffrant des valeurs de compteur incrémentales :

$$C_i = P_i \oplus E_K(Nonce \| Counter_i)$$

N‖1 N‖2 N‖3 E E E K P₁ P₂ P₃ C₁ C₂ C₃

Avantages : Parallélisable (chiffrement et déchiffrement), transforme un chiffrement par bloc en chiffrement à flot, accès aléatoire aux blocs

Inconvénients : Vulnérable si le nonce est réutilisé, pas d'authentification intégrée

Verdict : Recommandé avec nonces uniques

GCM (Galois/Counter Mode)

Extension du mode CTR avec une fonction d'authentification basée sur la multiplication en champ de Galois :

  • Utilise CTR pour le chiffrement
  • Calcule un tag d'authentification (GMAC) pour garantir l'intégrité
  • Permet d'authentifier des données additionnelles (AAD) non chiffrées

$$C_i = P_i \oplus E_K(IV \| Counter_i)$$

$$Tag = GHASH(AAD, C) \oplus E_K(IV \| 0)$$

CTR Chiff. GHASH AAD C Tag

Avantages : Parallélisable, fournit confidentialité et authentification (AEAD), très efficace sur le matériel moderne

Inconvénients : Catastrophique si le nonce est réutilisé, implémentation complexe

Verdict : Hautement recommandé pour les applications modernes

Modes opératoires avancés et spécialisés

ChaCha20-Poly1305

Combinaison du chiffrement à flot ChaCha20 et de l'authentificateur Poly1305 :

  • ChaCha20 : fonction de chiffrement à flot ARX (Addition-Rotation-XOR) créée par D.J. Bernstein
  • Poly1305 : fonction d'authentification MAC basée sur un polynôme

$$C = P \oplus ChaCha20(key, nonce, counter)$$

$$Tag = Poly1305(r, C)$$

où \(r\) est une clé dérivée de la clé principale et du nonce

Avantages : Très rapide sur les processeurs sans instructions AES-NI, résistant aux attaques par canal auxiliaire, sans tableau de substitution

Verdict : Recommandé particulièrement pour les appareils à ressources limitées

SIV (Synthetic Initialization Vector)

Mode de chiffrement authentifié conçu pour être résistant à la réutilisation de nonce :

  • Calcule d'abord un "IV synthétique" (S) basé sur les données à chiffrer
  • Utilise ensuite S comme nonce pour chiffrer les données avec CTR

$$S = CMAC_K(AAD \| P)$$

$$C = CTR_{K'}(S, P)$$

Avantages : Résistant à la réutilisation accidentelle de nonce/IV, idéal pour le chiffrement de stockage

Inconvénients : Nécessite deux passes sur les données, pas parallélisable pour le chiffrement

Verdict : Recommandé pour le chiffrement au repos et les environnements où la gestion de nonce est difficile

XTS (XEX-based Tweaked CodeBook mode with ciphertext Stealing)

Mode spécialisé pour le chiffrement de stockage (disques, secteurs) :

  • Utilise deux clés et un "tweak" (généralement le numéro de secteur)
  • Chaque bloc est chiffré indépendamment mais avec une modification basée sur sa position

$$C_j = E_{K1}(P_j \oplus (E_{K2}(i) \otimes \alpha^j)) \oplus (E_{K2}(i) \otimes \alpha^j)$$

où \(i\) est l'identifiant du secteur et \(\alpha\) est un élément primitif du champ de Galois

Avantages : Accès aléatoire aux blocs, pas de propagation d'erreurs, adapté au chiffrement de disque

Inconvénients : Pas d'authentification intégrée, vulnérable à certaines attaques de modification

Verdict : Recommandé spécifiquement pour le chiffrement de stockage

OCB (Offset CodeBook)

Mode de chiffrement authentifié parallélisable en une seule passe :

  • Utilise des "offsets" calculés à partir du nonce pour chaque bloc
  • Fournit l'authentification et le chiffrement en une seule passe

$$C_i = E_K(P_i \oplus \Delta_i) \oplus \Delta_i$$

$$Tag = E_K(\bigoplus_i (P_i \oplus C_i) \oplus \Delta_*)$$

Avantages : Très efficace (presque aussi rapide que le chiffrement CTR seul), entièrement parallélisable

Inconvénients : Protégé par des brevets jusqu'en 2021 (maintenant libre), légèrement plus vulnérable à la réutilisation de nonce que GCM

Verdict : Recommandé pour les applications nécessitant des performances optimales

Sécurité et vulnérabilités des modes opératoires

Vulnérabilité Description Modes affectés Contre-mesures
Révélation de motifs Blocs identiques produisant des chiffrés identiques ECB Utiliser des modes avec chaînage ou compteur (CBC, CTR)
Attaques par padding oracle Exploite les informations de validation du padding pour récupérer progressivement le texte clair CBC avec padding PKCS#7 Utiliser des modes AEAD, valider l'intégrité avant le padding
Réutilisation de nonce/IV Compromet gravement la sécurité si un nonce est réutilisé CTR, GCM, ChaCha20-Poly1305 Gestion stricte des nonces, utiliser des modes SIV
Attaques par bits flippés Modification délibérée de bits dans le chiffré pour produire des changements prévisibles dans le texte déchiffré Modes sans authentification (ECB, CBC, CTR) Utiliser des modes AEAD (GCM, ChaCha20-Poly1305)
Attaques par canal auxiliaire Exploitation du timing, de la consommation électrique ou des fuites EM pour récupérer des informations Tous les modes, mais particulièrement ceux avec des opérations à temps variable Implémentations à temps constant, protections matérielles

Recommandations pratiques pour le choix d'un mode opératoire

Guide de sélection des modes opératoires par cas d'usage
  • Communications réseau :
    • Privilégier AES-GCM ou ChaCha20-Poly1305
    • Utiliser des nonces incrémentaux ou aléatoires de taille suffisante
    • S'assurer que le récepteur vérifie le tag d'authentification avant d'utiliser les données déchiffrées
  • Chiffrement de fichiers :
    • Privilégier AES-GCM pour les petits fichiers
    • Considérer AES-SIV pour les fichiers fréquemment mis à jour
    • Stocker le tag d'authentification avec les données chiffrées
  • Chiffrement de disque/partition :
    • Privilégier AES-XTS
    • Considérer des solutions avec intégrité comme AEGIS si l'authentification est nécessaire
  • Environnements contraints :
    • Privilégier ChaCha20-Poly1305 sur les plateformes sans accélération AES
    • Considérer ASCON ou d'autres chiffrements légers standardisés pour l'IoT
  • Haute performance :
    • Privilégier AES-GCM avec accélération matérielle ou OCB
    • Utiliser AES-GCM-SIV si la gestion des nonces est problématique
Exemple : Utilisation d'AES-GCM en OpenSSL
# Génération d'une clé AES-256 aléatoire (32 octets)
openssl rand -out key.bin 32

# Génération d'un vecteur d'initialisation (IV/nonce) de 12 octets
openssl rand -out iv.bin 12

# Chiffrement avec AES-256-GCM
openssl enc -aes-256-gcm -in plaintext.txt -out ciphertext.bin \
  -K $(xxd -p -c 64 key.bin) \
  -iv $(xxd -p -c 24 iv.bin) \
  -out ciphertext.bin \
  -tag tag.bin

# Déchiffrement avec AES-256-GCM
openssl enc -d -aes-256-gcm -in ciphertext.bin \
  -K $(xxd -p -c 64 key.bin) \
  -iv $(xxd -p -c 24 iv.bin) \
  -tag tag.bin \
  -out decrypted.txt

Exercices associés

Mettez en pratique les concepts de ce chapitre avec les exercices dédiés.

Accéder aux exercices

Ressources complémentaires