Quel algorithme choisir, lequel fuir, et les fautes d'emploi (nonce, aléa, comparaison) qui ruinent même un bon algorithme.
Pourquoi ce livre
Un développeur web ne programme presque jamais un chiffrement. Il appelle une fonction, choisit un mode, un nonce, une taille de clé, et se demande si c'est sûr. Ce livre répond à cette question, et son message est net : les algorithmes sont rarement cassés, ce sont les emplois qui le sont. Un nonce répété, un générateur aléatoire de langage, une comparaison qui s'arrête au premier octet faux suffisent. L'auteur, Jean-Philippe Aumasson, est cryptographe de métier.
La fiche suit le chemin d'un message. D'abord le sens de « sûr » et l'aléa (idées 1 et 2), puis le chiffrement (3 et 4). Viennent le hachage et l'authentification (5 et 6), leur union (7), la clé publique (8 et 9) et TLS 1.3 (10). Le quantique (11), deux pièges et un aide-mémoire (12) terminent la liste.
Deux avertissements. L'auteur est concepteur de plusieurs fonctions qu'il compare : « Je dois le dire : je suis un des concepteurs de BLAKE2 » (p. 133). Il est aussi coauteur de BLAKE3 et de SipHash. Ensuite, les exemples sont surtout en Python et en OpenSSL (quelques listings Sage, C++ et un extrait Go). Aucune fonction crypto/rand, hmac.Equal ni hash_equals n'y figure, et chaque encadré « hors livre » ci-dessous fait ce pont.
Je l'ai ouvert pour combler le chapitre 7 du Grand livre, celui des primitives cryptographiques. Je voulais aussi savoir ce qu'il faut maîtriser avant un dépôt public mTLS en Go (mTLS : TLS où le client s'authentifie aussi, par certificat). Je laisse de côté la théorie de la complexité, les mathématiques internes d'AES et la blockchain.
Les idées qui restent
1Contre qui, et en combien de bits : le réflexe des 128 bits
On ne peut pas dire « c'est sûr » tout court. Le livre pose la règle : « on ne peut pas prétendre qu'un système est sûr sans expliquer contre qui ou contre quoi il l'est » (p. 12). Un chiffrement transforme un texte clair en chiffré à l'aide d'une clé secrète. Son modèle d'attaque décrit ce que l'attaquant peut faire.
Le livre en donne quatre, du plus faible au plus fort (pp. 13-14). Dans le COA (ciphertext-only attack, à chiffré seul), l'attaquant ne voit que des chiffrés. Dans le KPA (known-plaintext attack, à clair connu), il connaît aussi des clairs. Dans le CPA (chosen-plaintext attack, à clair choisi), il peut faire chiffrer ce qu'il veut. Dans le CCA (chosen-ciphertext attack, à chiffré choisi), il peut aussi faire déchiffrer. Une dernière famille regarde l'implémentation : temps d'exécution, messages d'erreur, consommation (p. 14). On parle de canaux auxiliaires. Un site qui répond « erreur de remplissage » à un message trafiqué en est un (idée 3).
Le principe de Kerckhoffs (1883) en tire la conséquence : « la sécurité d'un chiffrement devrait reposer uniquement sur le secret de la clé, pas sur celui du chiffrement » (p. 13). N'inventez pas votre algorithme. Le livre n'a qu'une preuve de confiance à offrir : beaucoup d'experts ont échoué à casser les standards (p. 53). Une preuve peut même être fausse : celle d'OAEP (idée 8) a été acceptée pendant sept ans (p. 56).
Pour mesurer la force, le livre compte en bits de sécurité : n bits, c'est environ 2^n opérations pour l'attaquant (p. 46). La force brute essaie toutes les clés. Sur une clé de 128 bits, à 100 milliards d'essais par seconde, elle dépasse 100 milliards de milliards d'années (p. 45). Le niveau d'un système se lit sur son maillon faible : un module RSA de 2 048 bits (n, idée 8) vaut moins de 128 bits (p. 46). Autre exemple : « des clés de 512 bits offrent un niveau de sécurité d'environ 60 bits » (p. 56). En 2015, des sites HTTPS et des serveurs SSH acceptaient encore de telles clés, cassables en deux semaines sur 72 processeurs (p. 56).
Plusieurs cibles abaissent la barre : chaque essai vise toutes les clés à la fois, donc casser l'une des 2^16 clés de 128 bits coûte 2^112 évaluations en moyenne (pp. 48-49). Le livre tranche : 128 ou 256 bits, jamais 64 ou 80 (p. 49).
Hors livre, décisions. Trois gestes en découlent. Visez 128 bits de sécurité au minimum. Refusez les clés courtes « pour compatibilité ». Évitez de chiffrer des données déjà compressées : un chiffrement sûr laisse fuir la longueur (p. 15), et la longueur compressée trahit le contenu (CRIME, idée 10).
2Une clé vaut son aléa : le générateur du système, jamais celui du langage
Une clé n'est qu'une suite d'octets au hasard. Si l'attaquant devine le hasard, l'algorithme ne sert plus à rien. Le livre distingue deux étages (pp. 28-29). Une source d'entropie (le désordre brut : bruit, frappes clavier, activité du système) est lente et manipulable. Un PRNG, générateur pseudo-aléatoire, la transforme en long flux imprévisible à partir d'une graine (sa valeur de départ). Quand il est conçu pour la sécurité, on parle de CSPRNG.
Sous Linux, voici l'interface : « Le fichier /dev/urandom est l'interface en espace utilisateur du PRNG cryptographique » (p. 34). L'appel système getrandom() est cité comme autre accès (p. 36). /dev/random, qui bloque, ne vaut pas mieux : « /dev/random n'était pas meilleur que /dev/urandom et posait plus de problèmes qu'il n'en résolvait » (p. 36). Sous Windows, BCryptGenRandom() est l'interface la plus simple (p. 37).
Le piège est le générateur du langage : « ne jamais utiliser de PRNG non cryptographique dans une application cryptographique, parce qu'ils ne sont pas sûrs » (p. 32). Le livre nomme rand et mt_rand de PHP (p. 32). Le Mersenne Twister de mt_rand est linéaire : chaque bit de sortie est un XOR (ou exclusif : 1 si les deux bits diffèrent, 0 sinon) de bits de l'état initial. Ces équations se résolvent : « à partir de quelques bits produits par MT, on peut deviner les bits suivants » (p. 32).
Trois histoires le montrent. En 2012, des chercheurs ont prédit les jetons et mots de passe temporaires de MediaWiki, générés avec mt_rand() (p. 40). Le code portait même ce commentaire : « Could be made more cryptographically sure if someone cares » (p. 40). En 2022, l'extension Trust Wallet tirait ses graines d'un Mersenne Twister limité à 32 bits d'entropie : 2^32 portefeuilles possibles, vidables avec quelques cartes graphiques en moins d'une journée (p. 305). En 1996, Netscape SSL avait une graine d'environ 47 bits au lieu de 128 (p. 39).
Un bon générateur ne suffit pas. En 2012, un balayage d'Internet a trouvé des clés publiques TLS et SSH identiques, ou partageant un facteur premier. Le générateur était correct, mais la clé était créée au premier démarrage, avant d'avoir assez d'entropie (pp. 39-40). Les tests statistiques ne rassurent pas : « les tests statistiques sont largement hors sujet pour la sécurité cryptographique » (p. 33). Enfin, un mauvais découpage ruine un bon CSPRNG : Cryptocat réduisait un octet à un chiffre par reste de division par 10 et acceptait <= 250 au lieu de < 250 : le 0 sortait une fois de trop, d'où un biais (p. 41).
Une clé symétrique, c'est n bits du CSPRNG, comme openssl rand -hex 16 (p. 54). Une clé asymétrique (paire clé publique et clé privée, idée 8) exige un algorithme de génération (p. 54). Pour la protéger, le livre cite trois voies : chiffrer la clé par une autre clé, la dériver d'un mot de passe, ou un jeton matériel (p. 55). Son aveu : « J'ai effectivement trouvé des clés privées sur GitHub » (p. 55).
Hors livre. En Go, c'est crypto/rand et jamais math/rand. En PHP, random_bytes() pour des octets et random_int() pour un entier, jamais rand() ni mt_rand(). Le livre ne cite aucune de ces fonctions.
3AES ne se casse pas : c'est le mode et le nonce qui vous perdent
Un chiffrement par blocs découpe le message en blocs de taille fixe et chiffre chacun avec la clé. AES a des blocs de 128 bits, DES de 64 bits (p. 62). Les petits blocs sont à fuir, car leur table de correspondance clair-chiffré devient constructible. À 64 bits, elle ferait 2^70 bits et le livre dit « oubliez ça » (p. 63). Sur AES lui-même, la meilleure attaque connue gagne un facteur 4 et exige 2^88 bits de paires (pp. 73-74). Ce n'est pas votre souci. Le vôtre est ailleurs : « la plus grande menace pour les chiffrements par blocs n'est pas dans leurs algorithmes de base mais dans leurs modes d'opération » (p. 74).
Un mode d'opération dit comment chiffrer un message de plusieurs blocs. Le mode ECB chiffre chaque bloc seul : deux blocs identiques donnent deux chiffrés identiques, ce que le livre montre avec deux blocs nuls (pp. 75-76). Verdict : « ECB n'est pas sûr, et vous ne devriez pas l'utiliser » (p. 74).
Le mode CBC mélange chaque bloc avec le chiffré du précédent. Le premier bloc reçoit un IV, valeur initiale qui doit être aléatoire et voyage en clair (p. 78). Hélas, « on utilise souvent CBC avec un IV constant au lieu d'un IV aléatoire » (p. 78). CBC exige des blocs complets, donc du padding : on complète avec des octets dont la valeur dit leur nombre. S'il manque un octet, on ajoute 01. Si le clair est déjà aligné, on ajoute 16 octets 10 (pp. 78-79).
Le padding ouvre la porte au padding oracle. Un oracle est un système qu'on interroge et dont les réponses renseignent l'attaquant. Ici, c'est un serveur qui réagit différemment selon la validité du padding (p. 83). Pour décrypter un bloc C2, l'attaquant le soumet derrière un faux bloc C1 et fait varier le dernier octet de C1 jusqu'à l'acceptation. C1 XOR (déchiffrement brut de C2) se termine alors par 01. Connaissant C1, il en déduit l'octet brut, puis, avec le vrai bloc précédent (public), l'octet du vrai clair (p. 84). Il recommence octet par octet : « L'attaque demande en moyenne 128 requêtes à l'oracle pour chacun des 16 octets, soit environ 2 000 requêtes au total » (p. 84). Le livre cite des serveurs d'applications web touchés en 2010 (p. 22). Sa parade vient plus tard : authentifier avant de déchiffrer (idée 7).
Le mode CTR chiffre un nonce (number used once) accolé à un compteur. Il en tire un flux de clé qu'on combine par XOR avec le clair. Il fait donc de AES un chiffrement de flux (idée 4). « Contrairement à la valeur initiale de CBC, le nonce de CTR n'a pas besoin d'être aléatoire : il doit simplement être unique » (p. 81). Sinon, deux chiffrés C1 et C2 du même flux donnent C1 XOR C2 = P1 XOR P2 : le flux de clé s'annule et les deux clairs se superposent (p. 81). Un nonce aléatoire de 64 bits se répète vers 2^32 messages (règle des anniversaires, idée 5) : « un nombre inacceptablement bas » (p. 82).
Hors livre. Le chiffrement qui n'authentifie pas appelle la parade de l'idée 7. Chez soi, on ne manipule ni ECB ni CBC à la main : on prend un mode authentifié (AES-GCM) via crypto/cipher en Go, ou ChaCha20-Poly1305 via libsodium en PHP.
4Un flux de clé ne sert qu'une fois : RC4 est mort, ChaCha20 reste
Un chiffrement de flux produit un flux de clé à partir d'une clé et d'un nonce public. Il le combine ensuite par XOR avec le clair (p. 88). Déchiffrer est la même opération. La règle est celle de l'idée 3 : ne jamais réutiliser le couple (clé, nonce) (p. 88). AES en CTR en est un cas : « l'un des chiffrements de flux les plus populaires est en fait un chiffrement par blocs déguisé » (p. 102).
RC4 (Rivest, 1987) fut le chiffrement de flux le plus répandu, dans WEP puis TLS. Son état est un tableau de 256 octets qu'on permute (p. 102). Son sort est une leçon d'humilité : « cela paraît trop simple pour être sûr, pourtant il a fallu 20 ans aux cryptanalystes pour trouver des failles exploitables » (p. 103).
WEP, la sécurité Wi-Fi d'origine, a mal réparé un manque : RC4 n'avait pas de nonce. WEP en a collé un de 24 bits devant la clé. Une « clé de 128 bits » WEP vaut au mieux 104 bits (p. 104). Avec 24 bits, un nonce tiré au hasard se répète après environ 2^12 paquets (p. 104). Pire, les trois octets de nonce visibles révèlent l'état du générateur après trois itérations, d'où une récupération de la clé (p. 104).
Dans TLS, la clé de session est unique, donc RC4 y est un peu moins cassé. Mais son deuxième octet de sortie vaut zéro avec une probabilité de 1/128 au lieu de 1/256 (p. 105). Le livre s'étonne : « ce qui est étonnant avec RC4, c'est qu'il échoue là où même beaucoup de PRNG non cryptographiques réussissent » (p. 105). En 2013, des experts lui faisaient encore confiance, alors que les biais étaient connus depuis 2001 (p. 105). TLS 1.3 l'a retiré (p. 266). Page 105, le livre classe l'attaque par diffusion de RC4 en CCA, alors qu'elle n'observe que des chiffrés (COA) : lapsus relevé en fin de fiche.
Salsa20 (Bernstein, 2005) est le successeur logiciel. Il travaille par compteur, sans état secret qui évolue, avec des additions, des rotations et des XOR sur des mots de 32 bits (pp. 106-107). Le livre décrit Salsa20 et cite ChaCha comme sa variante (p. 106). ChaCha20, le chiffrement de flux qui reste en usage, n'y est pas détaillé : il n'apparaît que sous le nom ChaCha20-Poly1305, l'un des trois chiffrements admis par TLS 1.3 (p. 265).
Décision : ni RC4 ni nonce bricolé. Un chiffrement de flux seul ne détecte pas une modification : il faut l'authentifier (idée 7).
5Hachage : SHA-2, SHA-3 ou BLAKE, jamais MD5 ni SHA-1
Une fonction de hachage prend une entrée de taille quelconque et rend une empreinte courte de taille fixe : « les fonctions de hachage prennent une longue entrée et produisent une courte sortie, appelée valeur de hachage ou empreinte » (p. 116). Ne la confondez pas avec une fonction non cryptographique comme CRC, qui détecte une erreur accidentelle et n'offre aucune sécurité (pp. 116, 135).
Trois résistances comptent (pp. 117-120). Une préimage est un message qui donne une empreinte donnée : la retrouver doit être impossible. Une seconde préimage est un autre message pour la même empreinte qu'un message connu. Une collision est une paire de messages qui ont la même empreinte. Résister aux collisions suppose les deux autres : qui trouve une seconde préimage a trouvé une collision. Or les collisions sont plus faciles à trouver : « trouver des collisions est plus rapide que trouver des préimages » (p. 120). C'est le paradoxe des anniversaires : dans une salle de 23 personnes, deux ont l'anniversaire le même jour avec une chance sur deux (p. 120). Il en va de même d'une empreinte de n bits : une paire collisionne dès environ 2^(n/2) messages, et non 2^n. SHA-256 offre donc 128 bits contre les collisions.
Le livre est tranché sur les anciens. MD5 : « il suffit de quelques secondes pour trouver une collision MD5, pourtant certains systèmes l'utilisent ou le supportent encore, souvent par compatibilité » (p. 127). SHA-1 : une vraie collision est arrivée 12 ans après l'estimation de 2005 (p. 129). Verdict : « Vous ne devez pas utiliser SHA-1 » (p. 129), « utilisez plutôt SHA-2, SHA-3, BLAKE2 ou BLAKE3 » (p. 129).
Les trois familles recommandées diffèrent par la construction. SHA-2 (SHA-256, SHA-512 en tête) enchaîne les blocs par compression (état et bloc deviennent un nouvel état), comme MD5 et SHA-1 (pp. 122, 129). Le livre est honnête : « il n'existe aucune preuve véritable que les fonctions SHA-2 soient sûres : on parle de sécurité probable » (p. 130). Le NIST (institut américain des normes) a lancé le concours SHA-3 en plan B : 64 candidats, 5 finalistes, et Keccak l'a gagné (pp. 131-132). Il repose sur une éponge, une permutation (mélange réversible) sans compression, complètement différente de SHA-2 (p. 132). Mais « malheureusement, SHA-3 n'est pas plus rapide que SHA-2 » (p. 133), d'où peu d'élan à migrer. BLAKE2 et BLAKE3 visent la vitesse, avec une clé secrète en option (pp. 133-135).
Un hachage sûr peut être mal employé. Prenons la preuve de stockage de la page 136 (|| désigne la concaténation). Le client envoie un défi C aléatoire. Le serveur répond Hash(M || C), censé prouver qu'il garde tout le fichier M. Mais le hachage est itératif : le serveur peut garder l'état après le premier bloc de M, jeter M, et répondre quand même. Avec C en tête, l'état dépend d'un C inconnu d'avance : il faut relire M. Le livre corrige : « demandez Hash(C || M) au lieu de Hash(M || C) » (p. 137).
Hors livre. crypto/sha256 en Go, hash('sha256', …) en PHP, rien de tout cela n'est dans le livre. Un hachage rapide ne convient pas aux mots de passe : le livre cite « la protection de mots de passe » parmi les usages (p. 115) sans en dire plus. Pour ce besoin, voir l'article Argon2 et l'oracle temporel du faux hash.
6Authentifier un message : HMAC, jamais H(clé || message), et comparer en temps constant
Un destinataire veut savoir que le message vient bien de l'expéditeur et n'a pas été modifié. On joint donc un tag, calculé par un MAC (code d'authentification de message) à partir d'une clé secrète : T = MAC(K, M) (p. 140). Le destinataire recalcule et compare. Le MAC ne bloque pas le rejeu, le renvoi d'un message authentique capturé. Parade : « pour empêcher ces attaques par rejeu, les protocoles incluent un numéro de message dans chaque message » (p. 141).
Tentation évidente : hacher la clé collée au message. Le livre prévient : « on pourrait croire qu'on fabrique une fonction de hachage à clé en donnant à un hachage une clé et un message, mais c'est plus facile à dire qu'à faire » (p. 142). Avec SHA-2, H(K || M) est forgeable par extension de longueur (pp. 136, 142). L'empreinte d'un hachage itératif est l'état interne après le dernier bloc. L'attaquant reprend à cet état et ajoute des blocs, sans connaître K : il obtient Hash(K || M1 || M2) à partir de Hash(K || M1). Le livre juge le défaut évitable : « cela aurait pu être évité simplement en rendant le dernier appel de compression différent de tous les autres » (p. 136). BLAKE2 et SHA-3 n'y sont pas sujets (p. 135).
Hash(M || K) n'est pas meilleur : si deux messages ont la même empreinte (une collision MD5 par exemple), ils ont le même tag quelle que soit la clé (p. 143). H(K || M) est aussi ambigu : K = 123abc avec M = def donne la même entrée que K = 123a avec M = bcdef (p. 143).
La réponse est HMAC : Hash((K XOR opad) || Hash((K XOR ipad) || M)), deux appels imbriqués avec des constantes d'habillage (p. 144). Il est utilisé par IPsec, SSH et TLS (le protocole de HTTPS, idée 10). Le livre en tire une règle : « si quelqu'un vous demande d'utiliser HMAC, demandez toujours “quelle fonction de hachage ?” » (p. 145). HMAC-SHA-256 est un nom complet. HMAC-MD5 et HMAC-SHA-1 ne sont pas totalement cassés, mais le risque est jugé élevé (p. 155). Poly1305 est un MAC très rapide (TLS 1.3, OpenSSH), mais son nonce ne doit jamais se répéter (pp. 148-151).
Dernière faute, la plus banale : la vérification. Une comparaison octet par octet s'arrête au premier octet faux : « le problème survient quand un serveur compare le bon tag à un mauvais en comparant les deux chaînes octet par octet, dans l'ordre, jusqu'à ce que les octets diffèrent » (p. 153). Le livre mesure, sur 100 000 appels : environ 67 ms quand les deux chaînes sont identiques et 26 ms quand elles diffèrent au troisième octet (p. 154). Un attaquant qui chronomètre devine le tag octet par octet. Le remède est du « code qui prend exactement le même temps pour toute valeur secrète en entrée » (p. 154).
Hors livre, esquisse non compilée. Le livre ne nomme pas ces fonctions, que l'on appelle ainsi.
mac := hmac.New(sha256.New, key)
mac.Write(msg)
ok := hmac.Equal(mac.Sum(nil), received) // temps constant
$ok = hash_equals(hash_hmac('sha256', $msg, $key, true), $received);
Jamais == ni bytes.Equal sur un secret.
7Chiffrer sans authentifier ne protège rien : prenez un chiffrement authentifié (AEAD), et un nonce qui ne revient jamais
Chiffrer cache le contenu mais n'empêche pas de le modifier. Combiner un chiffrement et un MAC se fait de trois façons (p. 158). Encrypt-and-MAC chiffre et authentifie le clair en parallèle (SSH). MAC-then-encrypt authentifie le clair puis chiffre le tout (TLS jusqu'à 1.2). Encrypt-then-MAC chiffre d'abord, puis authentifie le chiffré (IPsec). Encrypt-and-MAC a un défaut : « le tag d'authentification d'un clair pourrait quand même laisser fuir de l'information alors que le MAC est considéré comme sûr ! » (p. 159). MAC-then-encrypt en a un autre : le destinataire doit déchiffrer avant de savoir si le paquet est corrompu (p. 159). C'est la porte du padding oracle de l'idée 3 : le serveur déchiffre d'abord, et sa réaction trahit le padding. Avec encrypt-then-MAC, il rejette sans jamais déchiffrer (pp. 159-160). La condition : « tant que chacun est sûr en soi et que le MAC et le chiffrement utilisent des clés distinctes » (p. 158).
Un AEAD (chiffrement authentifié avec données associées) fait les deux en un seul appel. Il rend le chiffré et un tag. Au déchiffrement authentifié (noté AD dans le livre), « si la validation du tag échoue, AD renvoie une erreur pour empêcher le destinataire de traiter un clair qui a pu être falsifié » (p. 160). Les données associées sont authentifiées sans être chiffrées, comme l'en-tête d'un paquet (p. 160). Elles « doivent être encodées et sérialisées de façon sûre pour éviter une interprétation ambiguë de leur contenu » (p. 161). Et le nonce reste à votre charge : « c'est à l'opération de chiffrement de choisir un nonce jamais utilisé auparavant avec la même clé » (p. 161).
AES-GCM est l'AEAD le plus répandu. Il est standardisé (NIST SP 800-38D) et reconnu pour IPsec, SSH et TLS 1.2 et 1.3 (p. 164). Il combine le mode CTR de l'idée 3 avec un tag T = GHASH(H, A, C) XOR AES(K, N || 0) (pp. 164-166). A désigne les données associées, C le chiffré, N le nonce et H une clé interne d'authentification. GHASH est un hachage rapide qui mélange A et C avec H par des multiplications, sans autre secret (p. 165). Sa fragilité est le nonce répété : l'attaquant obtient le XOR des clairs (idée 3). Avec deux tags au même nonce, le terme AES s'annule dans leur XOR, qui devient GHASH(H, A1, C1) XOR GHASH(H, A2, C2) : tout y est connu sauf H. Les entrées et sorties de GHASH étant liées linéairement, cette équation livre H : l'attaquant forge alors des tags à volonté (p. 166). Ce n'est pas théorique : en 2016, 184 serveurs HTTPS répétaient leurs nonces, dont 23 avec un nonce toujours égal à zéro (p. 166).
Autre piège, les tags courts. Avec un tag de n bits, la chance de forgerie vaut 2^m/2^n, où 2^m est le nombre de blocs du plus long message observé. Prenons un tag de 48 bits et des messages de 4 Go (2^28 blocs de 16 octets). Cela fait 2^28/2^48 = 1/2^20, environ une chance sur un million : « une chance relativement élevée pour la cryptographie » (p. 173). Gardez 128 bits. Une valeur du livre est à corriger. Il donne 1/2^16 pour un tag de 32 bits et un message de 2 Mo. Sa formule, avec 2 Mo = 2^17 blocs de 16 octets, donne 1/2^15.
Le livre présente d'autres choix. OCB est plus simple et plus rapide, libre de brevet depuis 2021 (p. 167). SIV et GCM-SIV restent sûrs si un nonce se répète : « SIV reste sûr même si vous utilisez deux fois le même nonce » (p. 169), mais ils ne chiffrent pas au fil de l'eau : le tag dépend de tout le clair, qu'il faut donc garder en mémoire (p. 169). Notez que le livre ne dit nulle part de prendre GCM par défaut. Il constate que c'est le plus répandu, et que TLS 1.3 n'accepte que des AEAD (p. 265).
Hors livre, esquisse non compilée, erreurs ignorées. En Go, avec le paquet crypto/cipher.
gcm, _ := cipher.NewGCM(block) // block = aes.NewCipher(clé)
nonce := make([]byte, gcm.NonceSize()) // 12 octets
rand.Read(nonce) // crypto/rand
sealed := gcm.Seal(nonce, nonce, clair, entête) // nonce || chiffré || tag
Comptons : un nonce de 96 bits tiré au hasard se répète vers 2^48 messages par clé (règle des anniversaires de l'idée 5, p. 82). Le NIST SP 800-38D (§8.3), cité p. 164, impose en plus, dès que l'IV est tiré au hasard, au plus 2^32 chiffrements authentifiés par clé : une limite bien plus basse que les 2^48 de la règle des anniversaires.
8RSA aujourd'hui : 2 048 bits au minimum, OAEP pour chiffrer, PSS ou FDH pour signer
RSA repose sur un secret : deux grands nombres premiers p et q, dont le produit n = pq (le module) est public. Un exposant public e chiffre ou vérifie, un exposant privé d déchiffre ou signe (p. 198). Casser RSA revient à factoriser n. Le livre fixe la barre : « n devrait faire au moins 2 048 bits » (p. 199), soit environ 90 bits de sécurité, et 4 096 bits pour environ 128 (p. 199).
Première règle : « vous ne devriez pas utiliser la permutation à trappe RSA directement pour chiffrer ou signer » (p. 199). La permutation à trappe RSA, c'est x → x^e mod n, inversible par la seule clé privée. Telle quelle (« RSA brut »), elle est vulnérable : « le chiffrement RSA brut est déterministe : si vous chiffrez deux fois le même clair, vous obtiendrez deux fois le même chiffré » (p. 200). Il est aussi malléable : le produit de deux chiffrés est le chiffré du produit des clairs (p. 200). En pratique, RSA chiffre une clé symétrique, pas un message (p. 199).
Pour chiffrer, ajoutez un remplissage aléatoire qui rend le chiffrement probabiliste : « vous devez utiliser OAEP pour chiffrer avec RSA, plutôt que son prédécesseur, la norme PKCS#1 v1.5 » (p. 201). Avec un module de 2 048 bits et SHA-256, un OAEP porte au plus 190 octets de clé symétrique (p. 202).
Signer n'est pas chiffrer à l'envers : « signer avec RSA n'est pas la même chose que chiffrer avec la clé privée » (p. 202). La signature brute de x vaut x^d mod n : falsifiable pour x = 1, dont la signature est toujours 1 (p. 203). Elle est aussi vulnérable à l'aveuglement. Pour faire signer M à une victime qui refuserait, on lui fait signer R^e·M, d'apparence anodine. Sa signature vaut R·M^d : la diviser par R donne celle de M (p. 203). Deux schémas existent. PSS ajoute un sel (octets aléatoires mêlés au message). « OAEP n'a été prouvé sûr que pour le chiffrement, pas pour les signatures » (p. 204), donc PSS pour signer. FDH signe Hash(M)^d : « il est ennuyeusement simple, déterministe, et pourtant sûr » (p. 205). Le livre juge PSS complexe et sujet aux erreurs d'implémentation (p. 204).
Deux pièges d'implémentation, enfin. L'attaque par faute (Bellcore, 1996) provoque une erreur pendant une signature. Celle-ci est accélérée par le théorème des restes chinois (calcul séparé modulo p et modulo q). Si l'erreur touche le seul calcul modulo p, la signature fautive reste juste modulo q : le PGCD de n et de (signature fautive)^e − Hash(M) donne q, donc la clé privée (pp. 211-212). Elle « fonctionne sur FDH mais pas sur PSS, qui est probabiliste » (p. 211). Et deux clés ne partagent jamais le même module, car qui partage n connaît p et q, donc la clé privée de l'autre : « des paires de clés différentes doivent avoir des valeurs de module n différentes » (p. 212).
Le livre ajoute que les signatures RSA sont « de moins en moins utilisées » (p. 205) face à ECDSA et EdDSA.
Hors livre. Le livre ne nomme qu'une API, celle de Go. Il cite EncryptOAEP du paquet crypto/rsa et dit que PSS est dans OpenSSL et dans le module de cryptographie du langage Go (pp. 204, 206). Rien sur PHP (openssl_*).
9Courbes elliptiques : échange éphémère, signature Ed25519, nonce ECDSA à ne jamais perdre
Deux inconnus veulent partager un secret sur un réseau écouté. Diffie-Hellman (DH) le permet. Avec un nombre public g, Alice garde un secret a et publie A = g^a, Bob garde b et publie B = g^b. Alice calcule B^a, Bob calcule A^b : tous deux obtiennent g^ab, le secret partagé, sans l'envoyer (p. 216). L'espion qui voit A et B doit retrouver a : c'est le logarithme discret, réputé difficile. Mais « g^ab n'est pas une chaîne aléatoire » (p. 229). Dans l'exemple du livre (les nombres de 1 à 12 sur 4 bits), le premier bit vaut zéro dans 7 cas sur 12. C'est 0,58 au lieu de 0,5 (p. 229). Une clé doit être uniforme. Il faut donc passer le secret dans une KDF (fonction de dérivation de clé), par exemple HKDF (RFC 5869, p. 229).
DH tout nu est un « protocole simple, sûr contre les seuls attaquants les plus paresseux » (p. 223). Un homme du milieu s'intercale et partage un secret avec chacun. La parade est le DH authentifié : chaque partie signe son message avec sa clé à long terme (pp. 224-225). Il apporte la confidentialité persistante (forward secrecy) : si les clés de signature fuient un jour, les sessions passées restent illisibles, car « ils apprendraient les clés privées de signature mais aucun des exposants DH éphémères » (p. 225). Les « exposants » désignent ici les secrets a et b. Savoir si l'on tient la bonne clé publique reste à résoudre : c'est le sujet des certificats (idée 10).
Une courbe elliptique est l'ensemble des points (x, y) vérifiant une équation comme y² = x³ + ax + b (modulo un grand nombre premier). On sait y additionner deux points, par la droite qui les relie (p. 237). On sait donc multiplier un point par un entier k, en l'ajoutant k − 1 fois à lui-même (p. 238). DH s'y joue avec ces points : G est public, Alice publie aG (G ajouté a fois) et Bob publie bG. Le secret partagé est abG : chacun multiplie le point de l'autre par son secret (p. 241). Une courbe de 256 bits offre environ 128 bits de sécurité (p. 241). Deux courbes dominent. Les courbes NIST ont des constantes issues d'un hachage SHA-1 dont seule la NSA connaît l'origine. Pourtant la plupart des experts ne croient pas à une faille cachée (p. 247). Curve25519 (Bernstein, 2006) n'a pas de constante opaque, elle est plus rapide, et l'échange qu'elle permet s'appelle X25519 (pp. 248, 290). Elle sert dans WhatsApp, TLS 1.3 et OpenSSH (p. 248).
Pour signer, le livre préfère les courbes à RSA : « vous devriez préférer ECDSA à RSA sauf quand la vérification de signature est critique » (p. 244). ECDSA est l'Elliptic Curve Digital Signature Algorithm, la signature sur courbe elliptique. En RSA 4 096 bits, on mesure 303 signatures par seconde, contre 63 709 pour ECDSA sur P-256. La signature fait 512 bits contre 4 096 (pp. 243-244). Mais ECDSA a un piège mortel : le nonce de signature k. Une signature contient s = (h + rd)/k (h : hachage du message, d : clé privée, r : autre moitié de la signature, qui ne dépend que de k, donc identique dans les deux signatures). Avec le même k pour deux messages, s1 − s2 = (h1 − h2)/k, d'où k = (h1 − h2)/(s1 − s2), puis d = (s·k − h)/r (p. 249). Contrairement à RSA, un mauvais générateur aléatoire suffit à perdre la clé. Cas réel, la PlayStation 3 : « ils ont découvert que le même k avait été réutilisé pour signer des jeux différents » (p. 249).
Ed25519 supprime ce risque : son nonce est dérivé du message et de la clé, « éliminant les risques liés à un aléa défectueux » (p. 244). Il est dans le standard américain FIPS 186-5 depuis février 2023 et sert OpenSSH (p. 246). Son seul défaut est que la validation des signatures n'est pas uniforme : les implémentations n'appliquent pas toutes les mêmes critères (p. 250).
Deux validations sauvent aussi l'échange. Il faut vérifier les paramètres DH : en 2016, OpenSSL (CVE-2016-0701) acceptait un nombre premier non sûr comme paramètre DH (le modulo des calculs), d'où une fuite de clé privée (pp. 229-230). Il faut aussi vérifier les points de courbe reçus, car « on peut casser ECDH avec élégance si les points d'entrée ne sont pas correctement validés » (p. 249). Les formules d'addition n'utilisent pas le coefficient b de la courbe : l'attaquant envoie un point d'une autre courbe, de petit ordre. Le calcul de la victime reste alors dans un petit ensemble de valeurs, qu'il énumère pour retrouver le secret (pp. 249-250). Le test est de contrôler que les coordonnées satisfont l'équation de la courbe (p. 250).
Hors livre. En Go, utilisez crypto/ecdh (X25519) et crypto/ed25519. En PHP, utilisez sodium_crypto_kx_* et sodium_crypto_sign_*. Le livre n'en nomme aucune dans les pages lues, et son code est surtout en Python et OpenSSL.
10TLS 1.3 vu de la crypto : un aller-retour, trois suites, et ce que le livre ne dit pas du mTLS
TLS est le S de HTTPS : il chiffre et authentifie une connexion. Il a connu les défauts célèbres Heartbleed, BEAST, CRIME et POODLE (p. 256). Verdict sur la version actuelle : « TLS 1.3 est du TLS mûr » (p. 257). Il comporte deux protocoles : le handshake (la « poignée de main »), qui négocie les clés, et le record, qui les utilise pour les données (p. 257).
Le handshake tient en un aller-retour (p. 267). Le client envoie ses suites préférées (jeux d'algorithmes), une clé publique DH éphémère et un aléa de 32 octets. Le serveur répond avec sa propre clé publique, son certificat (voir plus bas), une signature sur l'ensemble et un MAC. Les deux côtés calculent le secret DH (idée 9) et en dérivent les clés avec HKDF (pp. 263-265). Le gain par rapport à TLS 1.2 : « le temps gagné peut se compter en centaines de millisecondes » (p. 267).
Ce que TLS 1.3 a retiré recoupe cette fiche (p. 266) : MD5, SHA-1, RC4, AES-CBC, MAC-then-encrypt et la compression (attaque CRIME). Il n'accepte que trois AEAD : AES-GCM, AES-CCM et ChaCha20-Poly1305 (p. 265). Il ajoute une protection contre la rétrogradation (forcer les deux côtés vers une vieille version vulnérable en trafiquant le message du client) : si ce message ne demande que du TLS 1.2, le serveur 1.3 met un motif fixe dans son aléa. Ce motif est signé, un intermédiaire ne peut pas l'effacer, et le client qui avait demandé du 1.3 voit la tromperie (pp. 266-267). Le livre écrit 8 bits pour les huit octets laissés aléatoires quand le client demande du TLS 1.3 (lapsus relevé en fin de fiche).
L'authentification passe par les certificats. Un certificat lie une clé publique à un domaine. Il est signé par une autorité de certification (CA), dont la clé est codée en dur dans le navigateur ou le système (pp. 258-260). Le livre n'est pas tendre : « les experts en sécurité et les cryptographes affirment souvent que tout le système de certificats est fondamentalement cassé » (p. 262), tout en le jugeant une des meilleures solutions disponibles (p. 262). Les limites sont dites : « la sécurité de TLS 1.3 repose sur l'hypothèse que les trois parties (le client, le serveur et l'autorité de certification) se comporteront honnêtement » (p. 269). DigiNotar, compromise en 2011, en est l'exemple (p. 269). Une injection ou un XSS passe dans un tunnel légitime : « TLS ne vous sauvera pas dans ce cas » (p. 270).
Pour le futur dépôt mTLS, voici ce que le livre apporte et ce qu'il tait. Il apporte la crypto : signature, DH éphémère, HKDF, AEAD. Sur le certificat client, il dit seulement : « vous utiliserez rarement des certificats clients, parce qu'ils compliquent les choses autant pour les clients que pour le serveur » (p. 268), et que le handshake peut exiger un certificat client (p. 265). Les mots « mutual TLS » et « mTLS » n'apparaissent pas (0 occurrence sur les 380 pages). La révocation retire un certificat avant son expiration : CRL est une liste de certificats révoqués, OCSP une interrogation en ligne de l'état d'un certificat. Le livre ne la cite que comme noms de champs dans un listing (p. 261). HSTS (HTTPS imposé à un site) et le pinning de certificat (n'accepter qu'un certificat précis) sont à 0 occurrence. Le 0-RTT envoie des données dès le premier message d'une session reprise (client déjà connu, sans handshake complet). Le livre ne le nomme que dans l'étiquette de la figure 13-2 (p. 267), sans l'expliquer et sans un mot sur le rejeu : un attaquant peut renvoyer ces premières données telles quelles (RFC 8446, section 8, hors livre), donc le 0-RTT n'est pas sans danger.
Hors livre. En Go, c'est crypto/tls avec ClientAuth: tls.RequireAndVerifyClientCert et un ClientCAs. Les données 0-RTT peuvent être rejouées (voir plus haut) : n'y mettez que des requêtes sans effet si elles sont exécutées deux fois (RFC 8446, section 8). Pour la suite, mes articles mTLS, SNI et liaison certificat-session et CRL à double barrière couvrent ce qui manque.
11Le quantique casse RSA et les courbes, pas AES : doublez les clés, passez en hybride
Un ordinateur quantique calcule avec des qubits, des bits quantiques qui valent 0 et 1 à la fois, ce qui accélère certains calculs. Un assez grand n'existe pas encore, mais il menacerait « toute la cryptographie à clé publique déployée ou standardisée à l'heure où j'écris » (p. 273). Deux algorithmes décident de tout. L'algorithme de Shor (1995) factorise et calcule les logarithmes discrets (retrouver a à partir de g^a, idée 9) en temps polynomial, sans explosion du coût. RSA, DH et les courbes tombent. Le livre dit qu'on pourrait « réduire la sécurité de RSA ou de la cryptographie à courbes elliptiques à celle du chiffre de César » (p. 281).
L'algorithme de Grover (1996) cherche dans n éléments en racine de n essais. Pour AES-128, la clé se trouve « en temps proportionnel à 2^64, au lieu de 2^128 avec des ordinateurs classiques seulement » (p. 283). La conclusion est rassurante : « on peut sauver les algorithmes symétriques des ordinateurs quantiques en doublant la taille de la clé ou de l'empreinte » (p. 283). D'où AES-256 et un hachage deux fois plus long. Les algorithmes à clé publique, eux, sont à remplacer.
Aucune date n'est promise. Mi-2024, le record était de 1 121 qubits. Il en faudrait « des millions, stables pendant des semaines, pour casser de la crypto » (p. 284).
Côté remplaçants, le NIST a lancé un concours en 2017 (69 soumissions), puis annoncé quatre standards en juillet 2022 (pp. 273, 290). CRYSTALS-Kyber est un KEM (mécanisme d'encapsulation de clé : il sert à établir une clé commune, comme DH). CRYSTALS-Dilithium et Falcon signent, et SPHINCS+ signe à partir de hachages seulement, pour ne pas dépendre d'une seule famille de problèmes mathématiques (p. 290). Le livre les appelle encore des projets de normes (FIPS, les normes fédérales américaines de traitement de l'information : 203, 204, 205). Il prévoit leur emploi en mode hybride, avec un algorithme classique en plus : « sont censés être d'abord utilisés en modes hybrides » (p. 290), par exemple Kyber avec X25519 dans TLS.
La priorité est l'échange de clés, pas la signature. Si une signature tombe, on révoque la clé (on la déclare invalide) et on re-signe. Mais pour un chiffrement vulnérable, « tous les chiffrés transmis pourraient être compromis » (p. 292). C'est l'idée que l'on nomme aujourd'hui récolter maintenant, déchiffrer plus tard, sans que le livre emploie l'expression (0 occurrence). Autre prudence : SIKE, finaliste, « s'est avéré totalement cassé peu après l'annonce » (p. 290), et les premières implémentations post-quantiques peuvent être moins sûres que les classiques (p. 292).
Hors livre, source NIST. Les noms ML-KEM, ML-DSA et SLH-DSA, absents du livre (0 occurrence), désignent Kyber, Dilithium et SPHINCS+. Ce sont les normes FIPS 203, 204 et 205, approuvées par le NIST le 13 août 2024 (csrc.nist.gov). Un échange hybride X25519 plus ML-KEM (X25519MLKEM768) est spécifié par l'IETF pour TLS 1.3. Il est activé par défaut dans crypto/tls depuis Go 1.24 (février 2025).
12Hacher sans ambiguïté, hacher tout le contexte, et l'aide-mémoire
Deux pièges du dernier chapitre du livre, consacré aux cryptomonnaies, se transposent partout. Premier piège, la séparation de domaine : deux entrées différentes ne doivent jamais donner la même chaîne à hacher. Hacher la concaténation de deux champs est ambigu : « vous obtiendrez la même valeur de hachage pour A = COL et B = LISION que pour A = CO et B = LLISION » (p. 305). Ce n'est pas une collision de la fonction, mais de l'application. Le remède est d'« encoder les valeurs d'entrée de l'application dans une chaîne unique par entrée, sans encodage ambigu » (p. 305), par exemple avec un séparateur : COL$LISION contre CO$LLISION. C'est la même faute que les clés de longueur variable de l'idée 6 et que les données associées de l'idée 7.
Second piège, Fiat-Shamir, la technique qui rend non interactive une preuve interactive (le vérificateur envoie un défi aléatoire) en calculant le défi par un hachage. Si ce hachage oublie une valeur, la preuve se falsifie. Le livre le montre avec la preuve de Schnorr, qui prouve qu'on connaît a derrière la clé publique A = aG. Le prouveur tire un nonce r, publie R = rG, calcule le défi c = H(G || R || A) et répond s = r + ca. Le vérificateur recalcule c et contrôle sG = R + cA, vrai puisque sG = rG + caG (p. 329). Sans R dans le hachage, c = H(G || A) ne dépend plus de R : l'attaquant fixe c, choisit s, puis calcule R = sG − cA, et l'égalité est vraie sans connaître a (p. 330). La leçon : « l'importance d'inclure toutes les valeurs nécessaires dans l'entrée de la fonction de hachage » (p. 330). Contre le rejeu, le livre conseille de mettre dans le hachage l'identité du prouveur, un identifiant de session ou un horodatage (p. 330).
Hors livre. En pratique, le jeton signé « user_id|montant » où 1|23 et 12|3 donnent la même chaîne est le cas de tous les jours. Encodez avec une longueur devant chaque champ, ou en JSON canonique. Appliqué à un jeton : incluez dans ce qui est signé l'audience et la durée de validité, sinon un jeton signé pour un service sert à un autre.
Aide-mémoire : ce que le livre fait choisir et fuir, avec les pages. Les lignes « chiffrer » et « signer » mêlent une règle explicite et une déduction de ma part, signalée par la ligne de lecture.
| Besoin | Choisir | Fuir | Pages |
|---|---|---|---|
| Hacher | SHA-2, SHA-3, BLAKE2 ou BLAKE3 | MD5, SHA-1, CRC pour la sécurité | 116, 127, 129 |
| Authentifier | HMAC avec un hachage nommé, comparaison en temps constant | H(clé, message), comparaison octet par octet | 142-145, 153-154 |
| Chiffrer | AEAD (AES-GCM, ChaCha20-Poly1305), nonce jamais répété | ECB, RC4, CBC à IV constant, chiffrement sans MAC | 74, 78, 102, 160, 265 |
| Signer | Ed25519 ou ECDSA, ou RSA 2 048 bits avec PSS ou FDH | RSA brut, nonce ECDSA répété | 199, 204, 244-249 |
| Échanger des clés | DH éphémère authentifié sur X25519, puis KDF | DH anonyme, paramètres et points non vérifiés | 225, 229, 249 |
| Aléa | CSPRNG du système | rand, mt_rand, graine maison | 32, 34 |
Mon avis, honnêtement
Deux questions comptaient pour moi. Ce livre m'apprend-il à choisir et à employer la crypto sans en faire mon métier ? Oui, et c'est son meilleur argument. Peut-il me servir directement en Go ou en PHP ? Non : les exemples sont surtout en Python et en OpenSSL, il faut traduire soi-même. Je l'ai lu comme on écoute un cryptographe sincère qui parle à un développeur : on retient les verdicts, on garde les preuves pour plus tard.
Sa force : il avoue. La NSA et le NIST connaissaient l'extension de longueur de SHA-2 (p. 136). On sort convaincu que la faute est dans l'emploi.
Deux réserves. L'auteur juge des fonctions qu'il a conçues : pour un site web courant, SHA-256 suffit, gardez BLAKE pour quand la vitesse compte. Ensuite, trois chiffres ou classements sont faux (liste en fin de fiche) : refaites un calcul avant de vous y fier.
Mon conseil : lisez les chapitres 1 et 2 sur les modèles d'attaque et l'aléa. Lisez ensuite les chapitres 4, 6, 7 et 8 sur les modes, le hachage, les MAC et l'AEAD. Terminez par le chapitre 13 sur TLS. Parcourez les chapitres 10 à 12 pour les règles, sautez les démonstrations de maths, et lisez le chapitre 14 en diagonale.
Odilon
Toujours valable en 2026 ?
Les verdicts durent : MD5 et SHA-1 à fuir, AEAD obligatoire, Ed25519 pour signer, TLS 1.3. Ce qui change la lecture :
- Post-quantique. Le livre de 2025 appelle encore Kyber, Dilithium et SPHINCS+ des projets de normes (p. 290). Les noms ML-KEM, ML-DSA et SLH-DSA font 0 occurrence, comme « harvest now ».
- Hors livre pour un site web. Mots de passe (Argon2 : une mention en biographie), mTLS, révocation, HSTS, pinning, rejeu du 0-RTT.
- Go et PHP. Go n'est cité que comme bibliothèque (pp. 152, 204, 206, 208), PHP qu'une fois (p. 32).
- Trois lapsus. Page 105, l'attaque par diffusion de RC4 est classée chosen-ciphertext alors qu'elle observe seulement des chiffrés (COA). Page 266, huit bits pour huit octets. Page 173, le tag de 32 bits : 1/2^16 au lieu de 1/2^15.
À qui s'adresse-t-il ?
Lisez-le si
- vous écrivez un backend PHP ou Go qui signe des jetons, chiffre des données ou parle TLS, et vous voulez savoir quoi choisir.
- vous avez au moins quelques années de métier et déjà utilisé
openssl, un JWT ou un certificat sans bien savoir pourquoi cela tenait. - vous préparez un déploiement mTLS et voulez les bases cryptographiques avant la configuration.
- vous aimez qu'un auteur prouve chaque conseil par un cas réel.
Passez si
- vous cherchez des recettes Go ou PHP à copier : le code est surtout en Python et OpenSSL.
- vous attendez un guide de mots de passe, de certificats clients ou de révocation : le livre n'en traite pas.
- les démonstrations mathématiques vous rebutent : les passages sur RSA, les courbes et les preuves en sont pleins.
Pour aller plus loin
- Le Grand livre du développeur, chapitre 7 sur la sécurité et les primitives, que cette fiche prolonge.
- TLS et HTTPS expliqués : le handshake et les certificats vus du réseau.
- Web Application Security : les failles applicatives que TLS ne couvre pas (idée 10).
- Defending APIs : jetons, signatures et authentification côté API.
- High Performance Browser Networking : le coût du handshake en latence.
- Mes articles : Argon2 et l'oracle temporel, mTLS, SNI et liaison de session, CRL à double barrière et le domaine d'échange crypto en DDD Go.
- Le livre est payant (No Starch Press), sans lien ici.
Fiche fondée sur : pages 12-22, 25-41, 44-56, 62-63, 71-85, 88-89, 102-109, 112-113, 115-145, 148-173, 198-213, 216-230, 241-250, 256-273, 281-293, 297-299, 304-305, 309-310 et 330-331 lues en détail. Reste trié mais non lu : structure interne d'AES, détail de ChaCha20, arithmétique des courbes, chapitre 9 et gros du chapitre 15. Les encadrés « hors livre », les calculs signalés et les vérifications d'absence sont de moi.
Commentaires (0)