<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cryptography on kenji.blog</title><link>http://kenji.blog/fr/tags/cryptography/</link><description>Recent content in Cryptography on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 21:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/cryptography/index.xml" rel="self" type="application/rss+xml"/><item><title>L'intuition mathématique de la cryptographie basée sur les réseaux (Lattice-based cryptography)</title><link>http://kenji.blog/fr/p/lattice-based-cryptography-math-intuition/</link><pubDate>Fri, 11 Sep 2026 21:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/lattice-based-cryptography-math-intuition/</guid><description>&lt;img src="http://kenji.blog/p/lattice-based-cryptography-math-intuition/img/eyecatch.jpg" alt="Featured image of post L'intuition mathématique de la cryptographie basée sur les réseaux (Lattice-based cryptography)" />&lt;h1 id="1-introduction--laube-de-la-cryptographie-post-quantique-pqc-et-lessor-de-la-cryptographie-basée-sur-les-réseaux">1. Introduction : L&amp;rsquo;aube de la cryptographie post-quantique (PQC) et l&amp;rsquo;essor de la cryptographie basée sur les réseaux
&lt;/h1>&lt;p>L&amp;rsquo;infrastructure numérique de la société moderne repose sur des technologies de cryptographie à clé publique telles que le chiffrement RSA et la cryptographie sur les courbes elliptiques (ECC). Ces méthodes cryptographiques basent leur sécurité sur la difficulté mathématique de problèmes tels que le &amp;ldquo;problème de la factorisation en nombres premiers&amp;rdquo; ou le &amp;ldquo;problème du logarithme discret&amp;rdquo;, qui sont considérés comme impossibles à résoudre efficacement (nécessitant un temps exponentiel) par les ordinateurs classiques conventionnels.&lt;/p>
&lt;p>Cependant, en 1994, l&amp;rsquo;algorithme de Shor, publié par Peter Shor, a provoqué une onde de choc dans le monde de la cryptographie. Cet algorithme a prouvé mathématiquement qu&amp;rsquo;une fois qu&amp;rsquo;un ordinateur quantique à grande échelle sera réalisé, il pourra résoudre les problèmes de factorisation en nombres premiers et de logarithme discret en un temps polynomial. Cela signifie que la cryptographie à clé publique largement utilisée aujourd&amp;rsquo;hui deviendra complètement décryptable à l&amp;rsquo;avenir.&lt;/p>
&lt;p>Pour contrer cette &amp;ldquo;menace quantique (Quantum Threat)&amp;rdquo;, il est devenu urgent de rechercher de nouvelles méthodes cryptographiques difficiles à décrypter, même avec un ordinateur quantique. C&amp;rsquo;est le domaine appelé &amp;ldquo;Cryptographie Post-Quantique (Post-Quantum Cryptography : PQC)&amp;rdquo; ou &amp;ldquo;Cryptographie résistante aux ordinateurs quantiques&amp;rdquo;.&lt;/p>
&lt;p>Il existe plusieurs candidats prometteurs pour la PQC, tels que la cryptographie basée sur les fonctions de hachage, sur les codes, sur des polynômes multivariés et sur les isogénies. Parmi eux, celle qui attire actuellement le plus l&amp;rsquo;attention et qui est au cœur du processus de standardisation PQC par le NIST (Institut national des normes et de la technologie des États-Unis) est la &amp;ldquo;cryptographie basée sur les réseaux (Lattice-based cryptography)&amp;rdquo;. Comparée à d&amp;rsquo;autres méthodes, la cryptographie basée sur les réseaux se distingue par une vitesse de traitement très élevée pour le chiffrement et le déchiffrement. De plus, elle possède une caractéristique remarquable en théorie cryptographique : une preuve de sécurité extrêmement solide basée sur la réduction de la &amp;ldquo;complexité dans le pire des cas (Worst-case complexity)&amp;rdquo; à la &amp;ldquo;complexité en moyenne (Average-case complexity)&amp;rdquo;.&lt;/p>
&lt;p>Dans cet article, nous partirons de la définition mathématique du &amp;ldquo;réseau (Lattice)&amp;rdquo; qui est à la base de cette cryptographie, pour expliquer en profondeur les problèmes difficiles sur les réseaux tels que le SVP (Problème du vecteur le plus court) et le CVP (Problème du vecteur le plus proche), ainsi que le problème LWE (Learning With Errors) qui est le cœur de la cryptographie moderne sur les réseaux. Nous utiliserons des formules mathématiques, des intuitions géométriques et des exemples numériques concrets.&lt;/p>
&lt;h1 id="2-définition-mathématique-et-intuition-géométrique-du-réseau-lattice">2. Définition mathématique et intuition géométrique du réseau (Lattice)
&lt;/h1>&lt;h2 id="21-espace-vectoriel-et-réseau">2.1 Espace vectoriel et réseau
&lt;/h2>&lt;p>En mathématiques, un &amp;ldquo;réseau (Lattice)&amp;rdquo; est un ensemble de points discrets disposés de manière régulière dans un espace vectoriel réel à $n$ dimensions $\mathbb{R}^n$. Il ressemble à un espace vectoriel (Vector Space) étudié en algèbre linéaire, mais il présente une différence cruciale. Alors qu&amp;rsquo;un espace vectoriel est un espace continu représenté par des combinaisons linéaires de vecteurs de base avec des &amp;ldquo;coefficients réels&amp;rdquo;, un réseau est un espace discret représenté par des combinaisons linéaires de vecteurs de base avec des &amp;ldquo;coefficients entiers&amp;rdquo;.&lt;/p>
&lt;p>Donnons une définition mathématique rigoureuse. Considérons $n$ vecteurs linéairement indépendants ($n \le m$) $\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n$ dans un espace vectoriel réel à $m$ dimensions $\mathbb{R}^m$. La matrice dont les colonnes sont ces vecteurs est notée $B = [\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n] \in \mathbb{R}^{m \times n}$. On appelle $B$ la &amp;ldquo;base (Basis)&amp;rdquo; du réseau.&lt;/p>
&lt;p>Le réseau $\mathcal{L}(B)$ généré par cette base $B$ est défini comme suit :&lt;/p>
$$
\mathcal{L}(B) = \left\{ \sum_{i=1}^{n} x_i \mathbf{b}_i \mathrel{\bigg|} x_i \in \mathbb{Z} \right\} = \{ B \mathbf{x} \mid \mathbf{x} \in \mathbb{Z}^n \}
$$
&lt;p>Ce qui est important ici, c&amp;rsquo;est que les coefficients $x_i$ sont restreints aux entiers $\mathbb{Z}$ et non aux nombres réels $\mathbb{R}$. Par conséquent, au lieu de former un nombre infini de points continus dans l&amp;rsquo;espace, cela forme un &amp;ldquo;ensemble de points discrets&amp;rdquo; semblables à des intersections espacées uniformément.&lt;/p>
&lt;h2 id="22-image-géométrique">2.2 Image géométrique
&lt;/h2>&lt;p>Considérons l&amp;rsquo;exemple du plan bidimensionnel $\mathbb{R}^2$. Si nous choisissons les vecteurs de base $\mathbf{b}_1 = \begin{pmatrix} 1 \\ 0 \end{pmatrix}$ et $\mathbf{b}_2 = \begin{pmatrix} 0 \\ 1 \end{pmatrix}$, le réseau généré par ceux-ci est l&amp;rsquo;ensemble de toutes les coordonnées entières $(x, y) \in \mathbb{Z}^2$ sur le plan cartésien. C&amp;rsquo;est le &amp;ldquo;réseau carré&amp;rdquo; le plus simple.&lt;/p>
&lt;p>Cependant, les réseaux ne sont pas toujours orthogonaux. Par exemple, si nous considérons la base $\mathbf{b}_1 = \begin{pmatrix} 2 \\ 1 \end{pmatrix}$ et $\mathbf{b}_2 = \begin{pmatrix} 1 \\ 3 \end{pmatrix}$, les points générés ressembleront aux intersections d&amp;rsquo;une maille déformée en biais.&lt;/p>
&lt;h2 id="23-non-unicité-de-la-base-et-transformation-unimodulaire">2.3 Non-unicité de la base et transformation unimodulaire
&lt;/h2>&lt;p>Il existe une propriété importante liée au fondement de la sécurité de la cryptographie sur les réseaux : &amp;ldquo;Il existe une infinité de bases qui génèrent le même réseau&amp;rdquo;.&lt;/p>
&lt;p>Par exemple, la base $\mathbf{b}_1 = (1, 0)^T, \mathbf{b}_2 = (0, 1)^T$ qui génère le réseau $\mathbb{Z}^2$, génère exactement le même réseau $\mathbb{Z}^2$ si nous utilisons la base $\mathbf{b}'_1 = (1, 1)^T, \mathbf{b}'_2 = (2, 3)^T$.&lt;/p>
&lt;p>Une condition nécessaire et suffisante pour qu&amp;rsquo;une base $B$ et une autre base $B'$ génèrent le même réseau est l&amp;rsquo;existence d&amp;rsquo;une matrice à coefficients entiers $U \in \mathbb{Z}^{n \times n}$ avec un déterminant $\det(U) = \pm 1$, telle que
&lt;/p>
$$ B' = B U $$
&lt;p>
Une telle matrice $U$ est appelée &amp;ldquo;matrice unimodulaire (Unimodular matrix)&amp;rdquo;.&lt;/p>
&lt;p>L&amp;rsquo;idée fondamentale dans son application à la cryptographie est d&amp;rsquo;utiliser une &amp;ldquo;bonne base (une base proche de l&amp;rsquo;orthogonalité, composée de vecteurs courts)&amp;rdquo; comme clé privée, et une &amp;ldquo;mauvaise base (une base avec des vecteurs extrêmement obliques les uns par rapport aux autres et très longs)&amp;rdquo; comme clé publique. Calculer une bonne base à partir d&amp;rsquo;une mauvaise base devient extrêmement difficile à mesure que la dimension augmente. C&amp;rsquo;est l&amp;rsquo;intuition fondamentale de la cryptographie basée sur les réseaux.&lt;/p>
&lt;h1 id="3-problèmes-mathématiquement-difficiles-dans-les-réseaux">3. Problèmes mathématiquement difficiles dans les réseaux
&lt;/h1>&lt;p>La sécurité de la cryptographie basée sur les réseaux repose sur la difficulté de résoudre certains problèmes mathématiques sur les réseaux. Nous présentons ici les deux problèmes les plus fondamentaux et célèbres.&lt;/p>
&lt;h2 id="31-problème-du-vecteur-le-plus-court-shortest-vector-problem-svp">3.1 Problème du vecteur le plus court (Shortest Vector Problem: SVP)
&lt;/h2>&lt;p>Le SVP est le problème le plus classique et célèbre de la théorie des réseaux.&lt;/p>
&lt;p>&lt;strong>Définition (SVP) :&lt;/strong>
Étant donné une base de réseau arbitraire $B$, trouver le vecteur $\mathbf{v}$ non nul appartenant à ce réseau $\mathcal{L}(B)$ qui a la norme euclidienne (longueur) minimale.&lt;/p>
&lt;p>Mathématiquement, c&amp;rsquo;est le problème de trouver $\mathbf{v}$ tel que $\min_{\mathbf{v} \in \mathcal{L}(B) \setminus \{\mathbf{0}\}} \| \mathbf{v} \|$. Cette longueur minimale est notée $\lambda_1(\mathcal{L})$ et est appelée le &amp;ldquo;premier minimum successif (First successive minimum) du réseau&amp;rdquo;.&lt;/p>
&lt;p>En basse dimension, comme en 2 ou 3 dimensions, vous pouvez trouver le vecteur le plus court à l&amp;rsquo;œil nu en dessinant un graphique, ou bien le résoudre efficacement en utilisant l&amp;rsquo;algorithme de réduction de base de Gauss. Cependant, lorsque la dimension $n$ atteint des centaines ou des milliers de dimensions, il est connu que résoudre strictement le SVP est un problème NP-difficile.&lt;/p>
&lt;p>Dans les systèmes cryptographiques réels, on utilise le SVP approché ($\gamma$-SVP), qui consiste à trouver un &amp;ldquo;vecteur approximativement court&amp;rdquo; au lieu du vecteur strictement le plus court. Lorsque le facteur d&amp;rsquo;approximation $\gamma$ est de taille polynomiale, ce problème est toujours considéré comme extrêmement difficile.&lt;/p>
&lt;h2 id="32-problème-du-vecteur-le-plus-proche-closest-vector-problem-cvp">3.2 Problème du vecteur le plus proche (Closest Vector Problem: CVP)
&lt;/h2>&lt;p>Le CVP est également un problème extrêmement important dans la cryptographie sur les réseaux.&lt;/p>
&lt;p>&lt;strong>Définition (CVP) :&lt;/strong>
Étant donné une base de réseau arbitraire $B$ et un vecteur cible arbitraire $\mathbf{t} \in \mathbb{R}^m$ dans l&amp;rsquo;espace (qui n&amp;rsquo;est pas nécessairement un point du réseau), trouver le point du réseau $\mathbf{v} \in \mathcal{L}(B)$ qui est le plus proche de $\mathbf{t}$.&lt;/p>
&lt;p>Mathématiquement, c&amp;rsquo;est le problème de trouver un point du réseau $\mathbf{v}$ tel que $\min_{\mathbf{v} \in \mathcal{L}(B)} \| \mathbf{v} - \mathbf{t} \|$.&lt;/p>
&lt;p>Le CVP, tout comme le SVP, est NP-difficile en haute dimension. Du point de vue des applications cryptographiques, le problème LWE décrit ci-dessous est étroitement lié à une variante spéciale de ce CVP (Bounded Distance Decoding: BDD).&lt;/p>
&lt;h2 id="33-pourquoi-est-il-impossible-de-les-résoudre-en-haute-dimension--limites-de-lll-et-bkz">3.3 Pourquoi est-il impossible de les résoudre en haute dimension ? (Limites de LLL et BKZ)
&lt;/h2>&lt;p>L&amp;rsquo;algorithme LLL (algorithme de Lenstra-Lenstra-Lovász) est un algorithme célèbre pour résoudre les problèmes de réseau en haute dimension. L&amp;rsquo;algorithme LLL fonctionne en temps polynomial et peut réduire (Reduction) la base du réseau en une &amp;ldquo;bonne base&amp;rdquo; dans une certaine mesure. Cependant, le vecteur le plus court que l&amp;rsquo;algorithme LLL peut trouver a un facteur d&amp;rsquo;approximation exponentiel ($2^{\mathcal{O}(n)}$) par rapport à la longueur du vrai vecteur le plus court, ce qui ne suffit pas pour briser la sécurité de la cryptographie.&lt;/p>
&lt;p>En utilisant des algorithmes de réduction de base plus puissants comme l&amp;rsquo;algorithme BKZ (Block Korkine-Zolotarev), qui est une amélioration de LLL, il est possible de trouver des vecteurs plus courts, mais la complexité de calcul augmente de manière exponentielle par rapport à la taille du bloc. Dans la cryptographie sur les réseaux, des paramètres de sécurité (comme la taille de la dimension $n$) sont déterminés en estimant le temps d&amp;rsquo;exécution de cet algorithme BKZ. Avec les paramètres standard actuels de la PQC, la dimension $n$ est choisie avec des valeurs de 500 à plus de 1000, et on estime qu&amp;rsquo;il faudrait un temps supérieur à l&amp;rsquo;âge de l&amp;rsquo;univers pour la déchiffrer, même avec des superordinateurs ou de futurs ordinateurs quantiques.&lt;/p>
&lt;h1 id="4-formulation-mathématique-du-problème-lwe-learning-with-errors">4. Formulation mathématique du problème LWE (Learning With Errors)
&lt;/h1>&lt;p>La majeure partie de la cryptographie moderne sur les réseaux est basée sur le &amp;ldquo;problème LWE (Learning With Errors)&amp;rdquo; proposé par Oded Regev en 2005. La beauté du problème LWE réside dans la simplicité de sa formulation et dans sa solide preuve mathématique basée sur &amp;ldquo;la réduction de la complexité dans le pire des cas à la complexité en moyenne&amp;rdquo;.&lt;/p>
&lt;h2 id="41-système-déquations-linéaires-sans-bruit">4.1 Système d&amp;rsquo;équations linéaires sans bruit
&lt;/h2>&lt;p>Pour comprendre le problème LWE, considérons d&amp;rsquo;abord un simple système d&amp;rsquo;équations linéaires sans bruit.
Supposons qu&amp;rsquo;il existe un vecteur secret inconnu $\mathbf{s} \in \mathbb{Z}_q^n$ (chaque composante est un entier de $0$ à $q-1$). Ici, $q$ est un nombre premier.&lt;/p>
&lt;p>Nous choisissons des vecteurs de coefficients aléatoires $\mathbf{a}_1, \mathbf{a}_2, \dots \in \mathbb{Z}_q^n$ et calculons le produit scalaire avec le vecteur secret $\mathbf{s}$ modulo $q$.
$b_1 = \langle \mathbf{a}_1, \mathbf{s} \rangle \pmod q$
$b_2 = \langle \mathbf{a}_2, \mathbf{s} \rangle \pmod q$
$\vdots$&lt;/p>
&lt;p>Si l&amp;rsquo;on nous donne un nombre suffisant (plus de $n$) de paires $(\mathbf{a}_i, b_i)$, nous pouvons facilement restaurer le vecteur secret $\mathbf{s}$ en utilisant l&amp;rsquo;&amp;ldquo;élimination de Gauss (Gaussian elimination)&amp;rdquo; en algèbre linéaire. C&amp;rsquo;est un problème qui peut être facilement résolu en temps polynomial.&lt;/p>
&lt;h2 id="42-définition-du-problème-lwe--ajout-de-bruit">4.2 Définition du problème LWE : Ajout de bruit
&lt;/h2>&lt;p>Alors, que se passe-t-il si nous ajoutons un léger &amp;ldquo;bruit (erreur)&amp;rdquo; à ce problème ?
C&amp;rsquo;est là l&amp;rsquo;essence du problème LWE.&lt;/p>
&lt;p>Pour un vecteur secret inconnu $\mathbf{s} \in \mathbb{Z}_q^n$, nous ajoutons une petite erreur $e_i \in \mathbb{Z}_q$ au résultat de chaque équation.
$b_i = \langle \mathbf{a}_i, \mathbf{s} \rangle + e_i \pmod q$&lt;/p>
&lt;p>Ici, $e_i$ est une petite valeur entière dont la moyenne est 0 et l&amp;rsquo;écart-type est relativement faible (par exemple, choisie à partir d&amp;rsquo;une distribution gaussienne discrète, similaire à une distribution normale).
L&amp;rsquo;information fournie est une liste de paires de vecteurs aléatoires $\mathbf{a}_i$ et de $b_i$ calculés en ajoutant l&amp;rsquo;erreur.
$( \mathbf{a}_1, b_1 ), ( \mathbf{a}_2, b_2 ), \dots, ( \mathbf{a}_m, b_m )$&lt;/p>
&lt;p>C&amp;rsquo;est beaucoup plus clair lorsqu&amp;rsquo;on l&amp;rsquo;exprime sous forme de matrice.
En utilisant une matrice aléatoire $A \in \mathbb{Z}_q^{m \times n}$, un vecteur secret $\mathbf{s} \in \mathbb{Z}_q^n$, et un vecteur d&amp;rsquo;erreur $\mathbf{e} \in \mathbb{Z}_q^m$, on peut écrire :
&lt;/p>
$$ \mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q $$
&lt;p>
Seuls $A$ et $\mathbf{b}$ sont fournis. Le &amp;ldquo;problème de recherche LWE (Search LWE problem)&amp;rdquo; consiste à trouver $\mathbf{s}$ à partir de cela.&lt;/p>
&lt;p>Puisque l&amp;rsquo;erreur $e_i$ est introduite, si l&amp;rsquo;on essaie d&amp;rsquo;utiliser l&amp;rsquo;élimination de Gauss, l&amp;rsquo;erreur s&amp;rsquo;amplifiera de manière exponentielle lors de l&amp;rsquo;addition et de la soustraction d&amp;rsquo;équations, et il deviendra impossible d&amp;rsquo;arriver à la bonne réponse. À première vue, cela ressemble à un simple système d&amp;rsquo;équations linéaires, mais l&amp;rsquo;ajout de ce petit bruit fait bondir le niveau de difficulté au stade NP-difficile.&lt;/p>
&lt;h2 id="43-problème-de-décision-lwe-decision-lwe">4.3 Problème de décision LWE (Decision LWE)
&lt;/h2>&lt;p>Une variante du problème de recherche LWE, appelée &amp;ldquo;problème de décision LWE (Decision LWE problem)&amp;rdquo;, est fréquemment utilisée dans les preuves en théorie cryptographique.&lt;/p>
&lt;p>Le problème de décision LWE est le problème de déterminer, étant donné une liste d&amp;rsquo;échantillons obtenus à partir des deux distributions suivantes, de quelle distribution elle provient.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Distribution LWE&lt;/strong> : $(A, \mathbf{b} = A\mathbf{s} + \mathbf{e} \pmod q)$ calculé intentionnellement.&lt;/li>
&lt;li>&lt;strong>Distribution aléatoire uniforme&lt;/strong> : $(A, \mathbf{u})$ constitué d&amp;rsquo;une matrice $A$ et d&amp;rsquo;un vecteur $\mathbf{u}$ choisis de manière totalement aléatoire.&lt;/li>
&lt;/ol>
&lt;p>Étonnamment, si les paramètres du problème LWE sont choisis de manière appropriée, les paires obtenues à partir de la distribution LWE deviennent &amp;ldquo;informatiquement indiscernables (Computationally Indistinguishable)&amp;rdquo; des paires de données totalement aléatoires. Cette propriété est la raison pour laquelle la cryptographie basée sur LWE peut générer &amp;ldquo;un texte chiffré indiscernable de nombres aléatoires&amp;rdquo;.&lt;/p>
&lt;h2 id="44-réduction-de-la-complexité-du-pire-des-cas-à-la-complexité-en-moyenne-théorème-de-regev">4.4 Réduction de la complexité du pire des cas à la complexité en moyenne (Théorème de Regev)
&lt;/h2>&lt;p>La plus grande réalisation d&amp;rsquo;Oded Regev a été de lier mathématiquement la difficulté de ce problème LWE à la difficulté des problèmes de réseaux susmentionnés (SVP et CVP).&lt;/p>
&lt;p>En utilisant la réduction quantique (Quantum reduction), il a prouvé que &amp;ldquo;s&amp;rsquo;il existe un algorithme en temps polynomial capable de résoudre le problème LWE en moyenne (pour des $A$ et $\mathbf{e}$ choisis aléatoirement), alors il existe un algorithme quantique en temps polynomial capable de résoudre le Gap-SVP pour le pire des cas (le cas le plus difficile) de n&amp;rsquo;importe quel réseau.&amp;rdquo; (Plus tard, une réduction classique a également été démontrée par Peikert et al.).&lt;/p>
&lt;p>C&amp;rsquo;est une propriété de rêve en théorie cryptographique. En effet, elle dissipe la crainte que &amp;ldquo;la cryptographie puisse être brisée parce que nous avons peut-être choisi par hasard une clé faible (une partie du cas moyen)&amp;rdquo;, et fournit la puissante garantie que &amp;ldquo;si le LWE moyen peut être résolu, alors tous les problèmes difficiles des réseaux peuvent être résolus (donc LWE est absolument difficile)&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
A["Problèmes de réseau dans le pire des cas (Gap-SVP, SIVP)"] -->|Réduction quantique/classique| B["Problème LWE en moyenne"]
B -->|Construction cryptographique| C["Systèmes cryptographiques basés sur LWE (PKE, KEM, FHE)"]
style A fill:#ffcccc,stroke:#ff0000,stroke-width:2px,color:#000
style B fill:#ccffcc,stroke:#00aa00,stroke-width:2px,color:#000
style C fill:#ccccff,stroke:#0000ff,stroke-width:2px,color:#000&lt;/div>
&lt;h1 id="5-construction-du-cryptosystème-à-clé-publique-basé-sur-lwe-cryptosystème-de-regev">5. Construction du cryptosystème à clé publique basé sur LWE (Cryptosystème de Regev)
&lt;/h1>&lt;p>Maintenant que nous avons compris la difficulté du problème LWE, examinons le cryptosystème à clé publique de base proposé par Oded Regev pour voir comment il est utilisé pour le chiffrement et le déchiffrement. Nous expliquerons ici le mécanisme le plus fondamental de chiffrement d&amp;rsquo;un message d&amp;rsquo;un bit $M \in \{0, 1\}$.&lt;/p>
&lt;h2 id="51-génération-de-clé-key-generation">5.1 Génération de clé (Key Generation)
&lt;/h2>&lt;ol>
&lt;li>En tant que paramètres du système, déterminez le module premier $q$, la dimension $n$, et le nombre d&amp;rsquo;équations $m$ ($m > n \log q$).&lt;/li>
&lt;li>En tant que clé privée, choisissez aléatoirement un vecteur $\mathbf{s} \in \mathbb{Z}_q^n$.&lt;/li>
&lt;li>Générez une matrice aléatoire $A \in \mathbb{Z}_q^{m \times n}$.&lt;/li>
&lt;li>Choisissez un petit vecteur d&amp;rsquo;erreur $\mathbf{e} \in \mathbb{Z}_q^m$ à partir d&amp;rsquo;une distribution d&amp;rsquo;erreur telle que la distribution gaussienne discrète.&lt;/li>
&lt;li>Calculez le vecteur $\mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q$.&lt;/li>
&lt;li>La clé publique (Public Key) sera $(A, \mathbf{b})$.&lt;/li>
&lt;li>La clé secrète (Secret Key) sera $\mathbf{s}$.&lt;/li>
&lt;/ol>
&lt;p>La clé publique est littéralement une &amp;ldquo;instance du problème LWE&amp;rdquo;. Puisque trouver la clé secrète $\mathbf{s}$ à partir de la clé publique $(A, \mathbf{b})$ équivaut à résoudre le problème de recherche LWE, la sécurité est garantie.&lt;/p>
&lt;h2 id="52-chiffrement-encryption">5.2 Chiffrement (Encryption)
&lt;/h2>&lt;p>Alice utilise la clé publique de Bob $(A, \mathbf{b})$ pour chiffrer un message d&amp;rsquo;un bit $M \in \{0, 1\}$.&lt;/p>
&lt;ol>
&lt;li>Choisissez un vecteur binaire aléatoire (dont les composantes sont 0 ou 1) $\mathbf{r} \in \{0, 1\}^m$.&lt;/li>
&lt;li>Comme première partie du texte chiffré, calculez le vecteur $\mathbf{u} = A^T \mathbf{r} \pmod q$. ($A^T$ est la matrice transposée de $A$. C&amp;rsquo;est-à-dire que nous additionnons les lignes de $A$ dont la composante correspondante de $\mathbf{r}$ est 1).&lt;/li>
&lt;li>Comme deuxième partie du texte chiffré, calculez le scalaire $v = \mathbf{b}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor \pmod q$.
(Si le message $M$ est 0, n&amp;rsquo;ajoutez rien ; s&amp;rsquo;il est $1$, ajoutez exactement la moitié de $q$, soit $\lfloor \frac{q}{2} \rfloor$).&lt;/li>
&lt;li>Le texte chiffré (Ciphertext) sera $(\mathbf{u}, v)$.&lt;/li>
&lt;/ol>
&lt;p>L&amp;rsquo;intuition derrière le chiffrement est de prendre la &amp;ldquo;somme d&amp;rsquo;un sous-ensemble aléatoire&amp;rdquo; par rapport à la matrice $A$ et au vecteur $\mathbf{b}$ de la clé publique. En raison de la difficulté du problème de décision LWE, ce texte chiffré $(\mathbf{u}, v)$ semble indiscernable de vecteurs totalement aléatoires et de nombres uniformément aléatoires (Sécurité sémantique : Semantic Security).&lt;/p>
&lt;div class="mermaid">flowchart LR
M["Message M dans {0,1}"] --> Enc
PK["Clé publique (A, b)"] --> Enc
r["Vecteur binaire aléatoire r"] --> Enc
subgraph Enc ["Processus de chiffrement"]
direction TB
u_calc["u = A^T * r mod q"]
v_calc["v = b^T * r + M * floor(q/2) mod q"]
end
Enc --> CT["Texte chiffré (u, v)"]&lt;/div>
&lt;h2 id="53-déchiffrement-decryption">5.3 Déchiffrement (Decryption)
&lt;/h2>&lt;p>Bob déchiffre le texte chiffré $(\mathbf{u}, v)$ en utilisant sa clé secrète $\mathbf{s}$.&lt;/p>
&lt;ol>
&lt;li>Calculez la valeur suivante : $D = v - \mathbf{s}^T \mathbf{u} \pmod q$&lt;/li>
&lt;li>Si le résultat calculé est proche de $0$, le message est de $M=0$, s&amp;rsquo;il est proche de $\lfloor \frac{q}{2} \rfloor$, le message est de $M=1$.&lt;/li>
&lt;/ol>
&lt;p>Montrons mathématiquement pourquoi cela permet le déchiffrement.
Rappelez-vous que $\mathbf{b} = A \mathbf{s} + \mathbf{e}$.&lt;/p>
$$
\begin{aligned}
v - \mathbf{s}^T \mathbf{u} &amp;= (\mathbf{b}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T (A^T \mathbf{r}) \\
&amp;= ((A \mathbf{s} + \mathbf{e})^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T A^T \mathbf{r} \\
&amp;= (\mathbf{s}^T A^T \mathbf{r} + \mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T A^T \mathbf{r} \\
&amp;= \mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor \pmod q
\end{aligned}
$$
&lt;p>Ici, le terme $\mathbf{s}^T A^T \mathbf{r}$ s&amp;rsquo;est parfaitement annulé et a disparu de l&amp;rsquo;équation !
Ce qui reste, c&amp;rsquo;est $\mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor$.&lt;/p>
&lt;p>$\mathbf{e}$ est un vecteur de bruit dont les composantes sont très petites, et $\mathbf{r}$ est un vecteur binaire dont les composantes sont 0 ou 1. Par conséquent, leur produit scalaire $\mathbf{e}^T \mathbf{r}$ restera également une valeur relativement faible (si les paramètres sont choisis de manière appropriée).&lt;/p>
&lt;ul>
&lt;li>Si $M=0$, le résultat sera $\mathbf{e}^T \mathbf{r}$, qui est une petite valeur proche de $0$.&lt;/li>
&lt;li>Si $M=1$, le résultat sera $\mathbf{e}^T \mathbf{r} + \lfloor \frac{q}{2} \rfloor$, qui sera situé autour de la moitié de $q$, soit $\lfloor \frac{q}{2} \rfloor$.&lt;/li>
&lt;/ul>
&lt;p>Si les paramètres sont conçus de sorte que la valeur absolue de l&amp;rsquo;erreur $\mathbf{e}^T \mathbf{r}$ soit inférieure à $\frac{q}{4}$, Bob peut déterminer (déchiffrer) avec précision le message $M$ en regardant simplement si le résultat du calcul est plus proche de $0$ ou de $\lfloor \frac{q}{2} \rfloor$. C&amp;rsquo;est le mécanisme élégant par lequel la cryptographie basée sur LWE fonctionne.&lt;/p>
&lt;div class="mermaid">flowchart LR
CT["Texte chiffré (u, v)"] --> Dec
SK["Clé secrète s"] --> Dec
subgraph Dec ["Processus de déchiffrement"]
direction TB
calc["Calculer D = v - s^T * u mod q"]
check["Vérifier si D est plus proche de 0 ou de q/2"]
end
calc --> check
Dec --> M_out["Message récupéré M"]&lt;/div>
&lt;h1 id="6-exemple-jouet-toy-example-de-chiffrement-lwe-avec-des-valeurs-numériques-spécifiques">6. Exemple jouet (Toy Example) de chiffrement LWE avec des valeurs numériques spécifiques
&lt;/h1>&lt;p>Il est difficile de comprendre seulement avec une liste de formules mathématiques, alors établissons des paramètres numériques très petits et suivons les calculs du chiffrement au déchiffrement.
(* Dans un système cryptographique réel, pour assurer la sécurité, $n$ est de 500 ou plus et $q$ est de plusieurs milliers).&lt;/p>
&lt;p>&lt;strong>【Paramétrage】&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Module $q = 17$ (Un nombre premier. Les valeurs seront donc de $0$ à $16$).&lt;/li>
&lt;li>Dimension $n = 2$&lt;/li>
&lt;li>Nombre d&amp;rsquo;équations $m = 4$&lt;/li>
&lt;li>Supposons que nous chiffrons le message $M = 1$.&lt;/li>
&lt;li>Montant du décalage du message : $\lfloor \frac{q}{2} \rfloor = \lfloor \frac{17}{2} \rfloor = 8$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>【1. Phase de génération de clé】&lt;/strong>
Bob choisit aléatoirement une clé secrète $\mathbf{s}$, une matrice $A$, et un vecteur d&amp;rsquo;erreur $\mathbf{e}$.
&lt;/p>
$$ \mathbf{s} = \begin{pmatrix} 3 \\ 4 \end{pmatrix} \in \mathbb{Z}_{17}^2 $$
$$ A = \begin{pmatrix} 2 &amp; 15 \\ 1 &amp; 8 \\ 14 &amp; 5 \\ 9 &amp; 10 \end{pmatrix} \in \mathbb{Z}_{17}^{4 \times 2} $$
$$ \mathbf{e} = \begin{pmatrix} 1 \\ -1 \\ 0 \\ 2 \end{pmatrix} \equiv \begin{pmatrix} 1 \\ 16 \\ 0 \\ 2 \end{pmatrix} \pmod{17} $$
&lt;p>Ensuite, calculez la clé publique $\mathbf{b}$.
&lt;/p>
$$ A \mathbf{s} = \begin{pmatrix} 2 &amp; 15 \\ 1 &amp; 8 \\ 14 &amp; 5 \\ 9 &amp; 10 \end{pmatrix} \begin{pmatrix} 3 \\ 4 \end{pmatrix} = \begin{pmatrix} 2\times 3 + 15\times 4 \\ 1\times 3 + 8\times 4 \\ 14\times 3 + 5\times 4 \\ 9\times 3 + 10\times 4 \end{pmatrix} = \begin{pmatrix} 6 + 60 \\ 3 + 32 \\ 42 + 20 \\ 27 + 40 \end{pmatrix} = \begin{pmatrix} 66 \\ 35 \\ 62 \\ 67 \end{pmatrix} $$
&lt;p>
Nous calculons cela modulo 17. (par exemple, $66 = 17 \times 3 + 15$)
&lt;/p>
$$ A \mathbf{s} \pmod{17} = \begin{pmatrix} 15 \\ 1 \\ 11 \\ 16 \end{pmatrix} $$
&lt;p>
Ajoutez le vecteur d&amp;rsquo;erreur $\mathbf{e}$.
&lt;/p>
$$ \mathbf{b} = A \mathbf{s} + \mathbf{e} = \begin{pmatrix} 15 \\ 1 \\ 11 \\ 16 \end{pmatrix} + \begin{pmatrix} 1 \\ 16 \\ 0 \\ 2 \end{pmatrix} = \begin{pmatrix} 16 \\ 17 \\ 11 \\ 18 \end{pmatrix} \equiv \begin{pmatrix} 16 \\ 0 \\ 11 \\ 1 \end{pmatrix} \pmod{17} $$
&lt;p>La clé publique est $A$ et $\mathbf{b} = (16, 0, 11, 1)^T$.&lt;/p>
&lt;p>&lt;strong>【2. Phase de chiffrement】&lt;/strong>
Alice chiffre le message $M = 1$.
Choisissez un vecteur aléatoire $\mathbf{r}$. Ici, supposons $\mathbf{r} = (1, 0, 1, 0)^T$.&lt;/p>
&lt;p>Calculez $\mathbf{u}$.
&lt;/p>
$$ \mathbf{u} = A^T \mathbf{r} = \begin{pmatrix} 2 &amp; 1 &amp; 14 &amp; 9 \\ 15 &amp; 8 &amp; 5 &amp; 10 \end{pmatrix} \begin{pmatrix} 1 \\ 0 \\ 1 \\ 0 \end{pmatrix} = \begin{pmatrix} 2 \times 1 + 14 \times 1 \\ 15 \times 1 + 5 \times 1 \end{pmatrix} = \begin{pmatrix} 16 \\ 20 \end{pmatrix} \equiv \begin{pmatrix} 16 \\ 3 \end{pmatrix} \pmod{17} $$
&lt;p>Calculez $v$.
&lt;/p>
$$ \mathbf{b}^T \mathbf{r} = (16, 0, 11, 1) \begin{pmatrix} 1 \\ 0 \\ 1 \\ 0 \end{pmatrix} = 16 \times 1 + 11 \times 1 = 27 \equiv 10 \pmod{17} $$
&lt;p>
Ajoutez la valeur $\lfloor 17/2 \rfloor = 8$ correspondant au message $M=1$.
&lt;/p>
$$ v = \mathbf{b}^T \mathbf{r} + M \cdot 8 = 10 + 1 \times 8 = 18 \equiv 1 \pmod{17} $$
&lt;p>Alice envoie le texte chiffré $(\mathbf{u}, v) = \left( \begin{pmatrix} 16 \\ 3 \end{pmatrix}, 1 \right)$ à Bob.&lt;/p>
&lt;p>&lt;strong>【3. Phase de déchiffrement】&lt;/strong>
Après avoir reçu le texte chiffré, Bob le déchiffre en utilisant la clé secrète $\mathbf{s} = (3, 4)^T$.
Formule de déchiffrement : calculez $D = v - \mathbf{s}^T \mathbf{u} \pmod{17}$.&lt;/p>
$$ \mathbf{s}^T \mathbf{u} = (3, 4) \begin{pmatrix} 16 \\ 3 \end{pmatrix} = 3 \times 16 + 4 \times 3 = 48 + 12 = 60 \equiv 9 \pmod{17} $$
$$ D = v - \mathbf{s}^T \mathbf{u} = 1 - 9 = -8 \pmod{17} $$
&lt;p>Ici, dans le monde modulo 17, $-8$ est égal à $9$ ($-8 + 17 = 9$).
Déterminez si la valeur obtenue $D = 9$ est plus proche de $0$ ou de $8$ ($\lfloor 17/2 \rfloor$).
Étant donné que $9$ est clairement plus proche de $8$ que de $0$, Bob a pu restaurer correctement $M = 1$ !&lt;/p>
&lt;p>Pourquoi est-ce devenu $9$ ? Rappelons la preuve précédente.
La partie d&amp;rsquo;erreur est $\mathbf{e}^T \mathbf{r} = (1, -1, 0, 2) (1, 0, 1, 0)^T = 1 \times 1 + 0 \times 1 = 1$.
Par conséquent, le résultat du calcul est $\mathbf{e}^T \mathbf{r} + M \cdot 8 = 1 + 8 = 9$, et il est confirmé que la valeur théorique a été calculée.&lt;/p>
&lt;h1 id="7-évolution-vers-une-application-pratique--ring-lwe-et-module-lwe">7. Évolution vers une application pratique : Ring-LWE et Module-LWE
&lt;/h1>&lt;p>Le problème LWE standard (Standard LWE) expliqué jusqu&amp;rsquo;à présent possède une preuve de sécurité très solide, mais présente un défaut fatal dans la pratique. C&amp;rsquo;est &amp;ldquo;la taille énorme de la clé&amp;rdquo; et le &amp;ldquo;coût de calcul élevé&amp;rdquo;.&lt;/p>
&lt;p>Dans le Standard LWE, la clé publique contient une énorme matrice $A \in \mathbb{Z}_q^{m \times n}$. Lorsque le paramètre $n$ atteint des centaines ou des milliers, la taille de cette matrice atteint plusieurs mégaoctets, ce qui est trop lourd pour être envoyé et reçu à chaque fois dans les protocoles de communication Internet (tels que TLS). De plus, la multiplication d&amp;rsquo;une matrice et d&amp;rsquo;un vecteur nécessite une complexité de calcul de $\mathcal{O}(n^2)$.&lt;/p>
&lt;p>Pour résoudre ce problème, on a introduit &amp;ldquo;Ring-LWE (RLWE)&amp;rdquo; et &amp;ldquo;Module-LWE (MLWE)&amp;rdquo;, qui intègrent une structure algébrique appelée anneaux de polynômes (Polynomial rings) dans le réseau.&lt;/p>
&lt;h2 id="71-intuition-de-ring-lwe">7.1 Intuition de Ring-LWE
&lt;/h2>&lt;p>Dans Ring-LWE, les vecteurs et les matrices sont remplacés par des éléments (polynômes) sur l&amp;rsquo;anneau de polynômes $\mathcal{R}_q = \mathbb{Z}_q[X]/(X^n + 1)$. (Ici, $n$ est choisi comme une puissance de 2).&lt;/p>
&lt;p>Alors que la clé publique de Standard LWE était la matrice $A$, Ring-LWE utilise un seul polynôme $a(x)$. La clé secrète $s(x)$ et l&amp;rsquo;erreur $e(x)$ deviennent également des polynômes.
L&amp;rsquo;équation est la suivante :
&lt;/p>
$$ b(x) = a(x) \cdot s(x) + e(x) \pmod q $$
&lt;p>Comme il s&amp;rsquo;agit d&amp;rsquo;une multiplication de polynômes, la complexité de calcul peut être considérablement réduite à $\mathcal{O}(n \log n)$ en utilisant la &amp;ldquo;Transformation Numérique Théorique (Number Theoretic Transform: NTT)&amp;rdquo;, qui est similaire à la Transformation de Fourier Rapide (FFT). De plus, puisque la taille de la clé publique est également réduite d&amp;rsquo;une matrice à un seul polynôme, la taille des données est réduite à $\mathcal{O}(n)$. Cela apporte un avantage écrasant en termes de bande passante de communication.&lt;/p>
&lt;p>D&amp;rsquo;un point de vue mathématique, Ring-LWE ne repose pas sur un réseau général, mais se réduit à un problème sur un réseau doté d&amp;rsquo;une symétrie spéciale appelé &amp;ldquo;réseau idéal (Ideal Lattice)&amp;rdquo;.&lt;/p>
&lt;h2 id="72-module-lwe-et-normalisation-du-nist-kyber--ml-kem">7.2 Module-LWE et normalisation du NIST (Kyber / ML-KEM)
&lt;/h2>&lt;p>Ring-LWE est efficace, mais il y avait quelques inquiétudes quant au fait que la structure algébrique spéciale du réseau idéal puisse devenir un indice pour de futures attaques. Ainsi, le &amp;ldquo;Module-LWE (MLWE)&amp;rdquo; a été créé en prenant le meilleur des deux mondes : la sécurité conservatrice de Standard LWE et l&amp;rsquo;efficacité de Ring-LWE.&lt;/p>
&lt;p>Dans Module-LWE, nous considérons de petites matrices et des vecteurs dont les éléments sont des polynômes. En d&amp;rsquo;autres termes, nous traitons des modules sur l&amp;rsquo;anneau.
Actuellement, &amp;ldquo;CRYSTALS-Kyber&amp;rdquo; (nom standardisé : ML-KEM), qui a été sélectionné par le NIST comme norme pour l&amp;rsquo;algorithme d&amp;rsquo;échange de clés PQC (KEM), est construit précisément sur la difficulté de ce problème Module-LWE.&lt;/p>
&lt;h1 id="8-pourquoi-est-ce-sûr-face-aux-ordinateurs-quantiques-">8. Pourquoi est-ce sûr face aux ordinateurs quantiques ?
&lt;/h1>&lt;p>Enfin, abordons le point essentiel : &amp;ldquo;Pourquoi considère-t-on que la cryptographie basée sur les réseaux ne sera pas brisée même avec des ordinateurs quantiques ?&amp;rdquo;&lt;/p>
&lt;p>L&amp;rsquo;algorithme de Shor, grâce auquel les ordinateurs quantiques brisent le chiffrement RSA et la cryptographie sur les courbes elliptiques, est essentiellement un algorithme qui résout le &amp;ldquo;problème du sous-groupe caché (Hidden Subgroup Problem: HSP)&amp;rdquo;. La structure mathématique derrière RSA et ECC (groupes abéliens finis) présente une périodicité, et en utilisant une opération spécifique à l&amp;rsquo;algorithme quantique appelée Transformée de Fourier Quantique (QFT), cette période (le sous-groupe caché) peut être extraite en une seule fois.&lt;/p>
&lt;p>Cependant, les problèmes de réseaux sont fondamentalement différents. Bien que les réseaux aient également une périodicité, ce qui est requis dans SVP et CVP sont des propriétés géométriques non linéaires telles que &amp;ldquo;la distance la plus courte&amp;rdquo; ou &amp;ldquo;la suppression du bruit&amp;rdquo;. Même si nous appliquons la &amp;ldquo;Transformée de Fourier quantique sur un groupe abélien&amp;rdquo; comme l&amp;rsquo;algorithme de Shor tel quel, nous ne pouvons pas extraire efficacement les informations utiles qui seraient la solution au problème du réseau. Jusqu&amp;rsquo;à présent, aucun algorithme quantique capable de résoudre SVP ou LWE en temps polynomial n&amp;rsquo;a été découvert, et on croit largement que même avec la capacité de calcul parallèle des ordinateurs quantiques, seuls des moyens de résolution proches d&amp;rsquo;une recherche par force brute (une accélération de l&amp;rsquo;ordre de la racine carrée grâce à l&amp;rsquo;algorithme de Grover) sont valables.&lt;/p>
&lt;h1 id="9-conclusion">9. Conclusion
&lt;/h1>&lt;p>Dans cet article, nous avons expliqué en détail l&amp;rsquo;intuition mathématique de la cryptographie sur les réseaux, en commençant par la définition géométrique du réseau, la formulation du problème LWE, et jusqu&amp;rsquo;à la construction d&amp;rsquo;une cryptographie à clé publique.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Le réseau (Lattice)&lt;/strong> est un espace discret représenté par des combinaisons linéaires à coefficients entiers de vecteurs de base, et il devient difficile de trouver une &amp;ldquo;bonne base&amp;rdquo; proche de l&amp;rsquo;orthogonalité dans les dimensions élevées (SVP).&lt;/li>
&lt;li>&lt;strong>Le problème LWE (Learning With Errors)&lt;/strong> est le problème de la résolution d&amp;rsquo;équations linéaires simultanées avec du bruit, ce qui est lié à la difficulté du problème du pire cas du réseau, fournissant ainsi une base solide de sécurité.&lt;/li>
&lt;li>En utilisant le problème LWE, le chiffrement et le déchiffrement (&lt;strong>Cryptosystème de Regev&lt;/strong>) sont réalisés grâce à un mécanisme ingénieux d&amp;rsquo;ajout et de suppression intentionnelle de bruit.&lt;/li>
&lt;li>Dans les protocoles réels, &lt;strong>Ring-LWE&lt;/strong> et &lt;strong>Module-LWE&lt;/strong> utilisant des anneaux de polynômes sont adoptés pour améliorer l&amp;rsquo;efficacité de la communication et la vitesse de calcul, et servent de base au &lt;strong>ML-KEM&lt;/strong> standard du NIST.&lt;/li>
&lt;/ol>
&lt;p>À l&amp;rsquo;approche du changement de paradigme informatique sans précédent que représentent les ordinateurs quantiques, il est très romantique de penser que la &amp;ldquo;cryptographie sur les réseaux&amp;rdquo;, née des profondeurs de l&amp;rsquo;algèbre linéaire classique et de la théorie des nombres, soutiendra la fondation de la sécurité Internet de demain. Les mathématiques qui sous-tendent la cryptographie sur les réseaux ne sont en aucun cas trop complexes, et avec des connaissances de base en algèbre linéaire et en probabilités, vous pouvez parfaitement comprendre sa belle structure. Nous espérons que cet article vous aidera à comprendre la cryptographie basée sur les réseaux, qui est au cœur de la PQC.&lt;/p></description></item><item><title>Hypothèse de Riemann et distribution des nombres premiers : une relation profonde avec la cryptographie moderne</title><link>http://kenji.blog/fr/p/riemann-hypothesis-prime-distribution-cryptography/</link><pubDate>Fri, 11 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/riemann-hypothesis-prime-distribution-cryptography/</guid><description>&lt;img src="http://kenji.blog/p/riemann-hypothesis-prime-distribution-cryptography/img/eyecatch.jpg" alt="Featured image of post Hypothèse de Riemann et distribution des nombres premiers : une relation profonde avec la cryptographie moderne" />&lt;h1 id="1-introduction--le-mystère-cosmique-des-nombres-premiers-et-lhypothèse-de-riemann">1. Introduction : Le mystère cosmique des nombres premiers et l&amp;rsquo;hypothèse de Riemann
&lt;/h1>&lt;p>Les « nombres premiers » (Prime Numbers) sont des entiers naturels qui ne sont divisibles que par 1 et par eux-mêmes, et sont souvent appelés les « atomes » du monde mathématique. La suite 2, 3, 5, 7, 11, 13&amp;hellip; semble à première vue désordonnée et aléatoire. Depuis que le mathématicien grec antique Euclide a prouvé qu&amp;rsquo;« il existe une infinité de nombres premiers », d&amp;rsquo;innombrables mathématiciens ont tenté de percer les régularités cachées dans cette suite de nombres premiers.&lt;/p>
&lt;p>Celle qui s&amp;rsquo;est le plus rapprochée du mystère des nombres premiers est l&amp;rsquo;&lt;strong>« Hypothèse de Riemann » (Riemann Hypothesis)&lt;/strong>, proposée en 1859 par le mathématicien allemand Bernhard Riemann. L&amp;rsquo;hypothèse de Riemann est l&amp;rsquo;un des problèmes les plus importants et non résolus des mathématiques modernes, et elle fait partie des Problèmes du prix du millénaire définis par l&amp;rsquo;Institut de mathématiques Clay, avec une récompense d&amp;rsquo;un million de dollars.&lt;/p>
&lt;p>À première vue, un problème difficile de mathématiques pures concernant la distribution des nombres premiers peut sembler sans rapport avec notre vie quotidienne. Cependant, la sécurité de l&amp;rsquo;infrastructure d&amp;rsquo;Internet qui soutient la société moderne, en particulier &lt;strong>les technologies de cryptographie moderne telles que le chiffrement RSA et la cryptographie sur les courbes elliptiques (ECC)&lt;/strong>, dépend profondément des propriétés des nombres premiers géants.&lt;/p>
&lt;p>Dans cet article, nous entreprendrons un voyage mathématique allant de la distribution des nombres premiers au théorème des nombres premiers, à la fonction zêta de Riemann, pour atteindre le cœur de l&amp;rsquo;hypothèse de Riemann. Nous explorerons en profondeur comment elle est liée à la cryptographie moderne et ce qu&amp;rsquo;il adviendrait du monde si l&amp;rsquo;hypothèse de Riemann venait à être prouvée.&lt;/p>
&lt;hr>
&lt;h1 id="2-le-théorème-des-nombres-premiers-et-la-distribution-des-nombres-premiers--la-découverte-de-gauss">2. Le théorème des nombres premiers et la distribution des nombres premiers : La découverte de Gauss
&lt;/h1>&lt;p>Afin de comprendre comment les nombres premiers sont distribués, les mathématiciens ont considéré la &lt;strong>fonction de compte des nombres premiers (Prime-counting function)&lt;/strong> $\pi(x)$, qui représente « combien de nombres premiers existent inférieurs ou égaux à un certain nombre $x$ ».&lt;/p>
&lt;p>Par exemple :&lt;/p>
&lt;ul>
&lt;li>$\pi(10) = 4$ (2, 3, 5, 7)&lt;/li>
&lt;li>$\pi(100) = 25$&lt;/li>
&lt;li>$\pi(1000) = 168$&lt;/li>
&lt;/ul>
&lt;p>Carl Friedrich Gauss, mathématicien de génie de 15 ans, a calculé d&amp;rsquo;énormes tables de nombres premiers et a découvert que la fréquence d&amp;rsquo;apparition des nombres premiers diminue de manière inversement proportionnelle au logarithme népérien $\ln x$. En d&amp;rsquo;autres termes, il a conjecturé que la probabilité de trouver un nombre premier autour d&amp;rsquo;un certain nombre $x$ est d&amp;rsquo;environ $\frac{1}{\ln x}$.&lt;/p>
&lt;p>L&amp;rsquo;expression de cela à l&amp;rsquo;aide d&amp;rsquo;une intégrale est le &lt;strong>logarithme intégral (Logarithmic integral)&lt;/strong> $\text{Li}(x)$.&lt;/p>
$$ \text{Li}(x) = \int_{2}^{x} \frac{dt}{\ln t} $$
&lt;p>La conjecture de Gauss a ensuite été prouvée indépendamment en 1896 par Jacques Hadamard et Charles-Jean de La Vallée Poussin, et a été établie en tant que &lt;strong>théorème des nombres premiers (Prime Number Theorem, PNT)&lt;/strong>.&lt;/p>
$$ \lim_{x \to \infty} \frac{\pi(x)}{\text{Li}(x)} = 1 $$
&lt;p>Ou de manière approximative, il s&amp;rsquo;exprime comme suit :&lt;/p>
$$ \pi(x) \sim \frac{x}{\ln x} $$
&lt;p>Grâce à ce théorème, nous savons que les nombres premiers ont une distribution très lisse et prévisible d&amp;rsquo;un point de vue macroscopique. Cependant, d&amp;rsquo;un point de vue microscopique, il existe toujours une « erreur » ou une « fluctuation » entre $\pi(x)$ et $\text{Li}(x)$. La véritable nature de cette fluctuation est le plus grand mystère que l&amp;rsquo;hypothèse de Riemann tente de résoudre.&lt;/p>
&lt;hr>
&lt;h1 id="3-la-fonction-zêta-de-riemann-et-le-produit-eulerien">3. La fonction zêta de Riemann et le produit eulerien
&lt;/h1>&lt;p>L&amp;rsquo;arme la plus puissante pour analyser la distribution des nombres premiers est la &lt;strong>fonction zêta de Riemann (Riemann Zeta Function)&lt;/strong>. À l&amp;rsquo;origine, il s&amp;rsquo;agissait d&amp;rsquo;une série infinie définie par Leonhard Euler pour les nombres réels $s > 1$.&lt;/p>
$$ \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s} = 1 + \frac{1}{2^s} + \frac{1}{3^s} + \frac{1}{4^s} + \dots $$
&lt;p>L&amp;rsquo;une des plus grandes réalisations d&amp;rsquo;Euler a été de prouver que cette série infinie peut être exprimée comme un produit infini sur tous les nombres premiers $p$. C&amp;rsquo;est le &lt;strong>produit eulerien (Euler Product Formula)&lt;/strong>.&lt;/p>
$$ \zeta(s) = \prod_{p \text{ prime}} \frac{1}{1 - p^{-s}} = \left( \frac{1}{1 - 2^{-s}} \right) \left( \frac{1}{1 - 3^{-s}} \right) \left( \frac{1}{1 - 5^{-s}} \right) \dots $$
&lt;p>La compréhension intuitive de la preuve est que si vous développez chaque terme du côté droit comme une série géométrique et que vous les multipliez, le théorème fondamental de l&amp;rsquo;arithmétique (tout entier naturel est exprimé de manière unique comme un produit de nombres premiers) reconstruira parfaitement la somme des inverses des entiers naturels du côté gauche.&lt;/p>
&lt;p>&lt;strong>Cette seule équation est devenue un pont reliant l&amp;rsquo;analyse (séries infinies / fonctions continues) et la théorie des nombres (nombres premiers / nombres discrets).&lt;/strong> Étudier la fonction zêta est synonyme d&amp;rsquo;étudier la distribution des nombres premiers.&lt;/p>
&lt;hr>
&lt;h1 id="4-prolongement-analytique-et-extension-au-plan-complexe">4. Prolongement analytique et extension au plan complexe
&lt;/h1>&lt;p>Le génie de Riemann réside dans l&amp;rsquo;extension de la variable $s$ de $\zeta(s)$, qu&amp;rsquo;Euler ne considérait que pour les nombres réels, à des &lt;strong>nombres complexes $s = \sigma + it$ ($\sigma$ est la partie réelle, $t$ est la partie imaginaire)&lt;/strong>.&lt;/p>
&lt;p>La série infinie originale ne converge que pour $\sigma > 1$, mais Riemann a utilisé une méthode appelée « prolongement analytique (Analytic Continuation) » pour étendre la définition de sorte que $\zeta(s)$ ait un sens sur l&amp;rsquo;ensemble du plan complexe, à l&amp;rsquo;exception du pôle en $s = 1$.&lt;/p>
&lt;p>Il a en outre dérivé une magnifique équation fonctionnelle (Functional equation) satisfaite par la fonction zêta.&lt;/p>
$$ \zeta(s) = 2^s \pi^{s-1} \sin\left(\frac{\pi s}{2}\right) \Gamma(1-s) \zeta(1-s) $$
&lt;p>Où $\Gamma(x)$ est la fonction gamma. Cette équation nous permet de connaître les propriétés du demi-plan gauche à partir des propriétés du demi-plan droit.&lt;/p>
&lt;h3 id="zéros-zeros-of-the-zeta-function">Zéros (Zeros of the Zeta Function)
&lt;/h3>&lt;p>Les nombres complexes $s$ où la valeur de la fonction zêta devient 0 sont appelés « zéros ».
D&amp;rsquo;après l&amp;rsquo;équation fonctionnelle, lorsque $s$ est un nombre pair négatif ($-2, -4, -6, \dots$), $\sin(\pi s / 2)$ devient 0, donc $\zeta(s) = 0$. Ceux-ci sont appelés les &lt;strong>zéros triviaux (Trivial zeros)&lt;/strong>.&lt;/p>
&lt;p>Cependant, ce qui est important dans la distribution des nombres premiers, ce sont les autres zéros, à savoir les &lt;strong>zéros non triviaux (Non-trivial zeros)&lt;/strong> qui existent dans la « bande critique (Critical strip) » où $0 \le \sigma \le 1$.&lt;/p>
&lt;hr>
&lt;h1 id="5-le-cœur-de-lhypothèse-de-riemann-et-la-formule-explicite">5. Le cœur de l&amp;rsquo;hypothèse de Riemann et la formule explicite
&lt;/h1>&lt;p>Riemann a calculé un petit nombre de zéros et a formulé une conjecture étonnante. C&amp;rsquo;est l&amp;rsquo;&lt;strong>hypothèse de Riemann&lt;/strong>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Hypothèse de Riemann (Riemann Hypothesis)&lt;/strong>
Tous les zéros non triviaux de la fonction zêta de Riemann $\zeta(s)$ ont une partie réelle égale à $1/2$ (c&amp;rsquo;est-à-dire $\text{Re}(s) = 1/2$).&lt;/p>
&lt;/blockquote>
&lt;p>Cette droite où la partie réelle est de 1/2 est appelée la « droite critique (Critical line) ».&lt;/p>
&lt;div class="mermaid">graph TD
A["Fonction zêta de Riemann ζ(s)"] --> B["Extension au plan complexe par prolongement analytique"]
B --> C["Zéros triviaux (s = -2, -4, -6 ...)"]
B --> D["Zéros non triviaux (0 &lt;= Re(s) &lt;= 1)"]
D --> E["Hypothèse de Riemann"]
E --> F["Tous les zéros non triviaux sont sur Re(s) = 1/2"]
F --> G["Vers la preuve de la limite du terme d'erreur de la distribution des nombres premiers"]&lt;/div>
&lt;p>Pourquoi l&amp;rsquo;hypothèse de Riemann est-elle si importante ? C&amp;rsquo;est parce que les zéros de la fonction zêta déterminent &lt;strong>complètement&lt;/strong> la distribution des nombres premiers.&lt;/p>
&lt;p>Riemann, et plus tard le mathématicien von Mangoldt, ont dérivé une « formule explicite (Explicit formula) » qui décrit avec précision la distribution des nombres premiers. En utilisant la fonction de Tchebychev $\psi(x)$, elle s&amp;rsquo;exprime comme suit :&lt;/p>
$$ \psi(x) = x - \sum_{\rho} \frac{x^\rho}{\rho} - \ln(2\pi) - \frac{1}{2}\ln(1 - x^{-2}) $$
&lt;p>Où $\rho$ est la somme sur tous les zéros non triviaux de la fonction zêta.
Le terme principal est $x$ (qui correspond au théorème des nombres premiers), et en ajoutant et en soustrayant des termes ondulatoires dépendant des zéros $\rho$, la distribution en escalier exacte des nombres premiers est restaurée. On peut dire que les zéros non triviaux représentent les « fréquences (ondes) » de la distribution des nombres premiers.&lt;/p>
&lt;p>Si l&amp;rsquo;hypothèse de Riemann est vraie, et que la partie réelle de tous les zéros non triviaux $\rho$ est exactement de $1/2$, alors le terme d&amp;rsquo;erreur du théorème des nombres premiers se situera dans la plus petite plage théoriquement concevable.&lt;/p>
$$ |\pi(x) - \text{Li}(x)| \le \frac{1}{8\pi} \sqrt{x} \ln x \quad \text{for} \quad x \ge 2657 $$
&lt;p>En d&amp;rsquo;autres termes, &lt;strong>si l&amp;rsquo;hypothèse de Riemann est vraie, il sera prouvé que les nombres premiers sont distribués de la manière la plus « régulière et belle » que nous puissions imaginer&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="6-la-cryptographie-moderne-et-sa-relation-indissociable-avec-les-nombres-premiers">6. La cryptographie moderne et sa relation indissociable avec les nombres premiers
&lt;/h1>&lt;p>Jusqu&amp;rsquo;ici, nous étions dans le monde profond des mathématiques pures, mais ces propriétés des nombres premiers soutiennent fondamentalement la société numérique moderne. Le représentant de cela est la cryptographie à clé publique telle que le &lt;strong>chiffrement RSA&lt;/strong>.&lt;/p>
&lt;p>La sécurité de toutes les communications, y compris les paiements par carte de crédit sur Internet, la transmission de mots de passe et les signatures numériques de la blockchain, dépend des « nombres premiers ».&lt;/p>
&lt;h3 id="fonctionnement-du-chiffrement-rsa">Fonctionnement du chiffrement RSA
&lt;/h3>&lt;p>La sécurité du chiffrement RSA est basée sur le fait mathématique (problème de la factorisation) qu&amp;rsquo;« il est très difficile de factoriser un nombre composé avec un grand nombre de chiffres ».&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Génération de clés&lt;/strong>:
Choisissez au hasard de très grands nombres premiers $p$ et $q$ (par exemple, 2048 bits chacun).
Multipliez-les pour calculer $N = p \times q$. Ce $N$ fera partie de la clé publique.
En utilisant l&amp;rsquo;indicatrice d&amp;rsquo;Euler $\phi(N) = (p-1)(q-1)$, générez la clé privée $d$.&lt;/p>
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Chiffrement et déchiffrement&lt;/strong>:
Le texte en clair $M$ est converti en texte chiffré $C$ à l&amp;rsquo;aide de la clé publique $e, N$.
&lt;/p>
$$ C \equiv M^e \pmod{N} $$
&lt;p>
Seul celui qui possède la clé privée $d$ peut le déchiffrer.
&lt;/p>
$$ M \equiv C^d \pmod{N} $$
&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["Texte en clair (Plaintext)"] --> B["Chiffrer avec la clé publique (e, N)"]
B --> C["Texte chiffré (Ciphertext)"]
C --> D["Déchiffrer avec la clé privée (d)"]
D --> E["Texte en clair original"]
F["Attaquant (Attacker)"] -- "Tente de factoriser N" --> C
F -.-> G["Impossible de calculer d sans connaître p et q"]&lt;/div>
&lt;p>Pour casser le chiffrement RSA, il faut trouver (factoriser) les nombres premiers originaux $p$ et $q$ à partir du gigantesque $N$. Même en utilisant les algorithmes les plus courants (Crible algébrique : GNFS, etc.), la factorisation d&amp;rsquo;un nombre de centaines de chiffres prendrait un temps dépassant de loin l&amp;rsquo;âge de l&amp;rsquo;univers, même avec des superordinateurs.&lt;/p>
&lt;hr>
&lt;h1 id="7-limpact-de-lhypothèse-de-riemann-sur-la-cryptographie">7. L&amp;rsquo;impact de l&amp;rsquo;hypothèse de Riemann sur la cryptographie
&lt;/h1>&lt;p>Alors, comment « l&amp;rsquo;hypothèse de Riemann » au sommet des mathématiques pures et la « cryptographie » se croisent-elles ?&lt;/p>
&lt;h3 id="71-algorithmes-de-génération-de-nombres-premiers-test-de-primalité-et-lhypothèse-de-riemann-généralisée-grh">7.1. Algorithmes de génération de nombres premiers (test de primalité) et l&amp;rsquo;hypothèse de Riemann généralisée (GRH)
&lt;/h3>&lt;p>Pour utiliser le chiffrement RSA, il faut d&amp;rsquo;abord générer des nombres premiers géants $p$ et $q$. Cependant, déterminer de manière fiable et rapide si « un certain nombre est premier » n&amp;rsquo;est pas facile.&lt;/p>
&lt;p>Actuellement, l&amp;rsquo;algorithme pratique utilisé est le &lt;strong>test de primalité de Miller-Rabin (Miller-Rabin primality test)&lt;/strong>, qui est un algorithme probabiliste. Cet algorithme est rapide, mais il existe un risque de « pseudo-premiers » où un nombre composé est identifié à tort comme premier avec une probabilité extrêmement faible.&lt;/p>
&lt;p>Cependant, si l&amp;rsquo;&lt;strong>« Hypothèse de Riemann généralisée (Generalized Riemann Hypothesis, GRH) »&lt;/strong>, qui étend l&amp;rsquo;hypothèse de Riemann aux fonctions L de Dirichlet, est supposée vraie, la situation change radicalement.
Si la GRH est vraie, la limite supérieure du nombre de tests dans le test de Miller-Rabin est mathématiquement garantie, et elle passe d&amp;rsquo;un algorithme probabiliste à un &lt;strong>« algorithme déterministe en temps polynomial »&lt;/strong> (C&amp;rsquo;était un fait majeur connu avant même la découverte du test de primalité AKS).&lt;/p>
&lt;p>En d&amp;rsquo;autres termes, l&amp;rsquo;hypothèse de Riemann (et son extension) joue un rôle dans l&amp;rsquo;approbation directe de la génération de base de la cryptographie : « Pouvons-nous générer des nombres premiers géants rapidement et avec une confiance absolue ? ».&lt;/p>
&lt;h3 id="72-relation-avec-les-algorithmes-de-factorisation">7.2. Relation avec les algorithmes de factorisation
&lt;/h3>&lt;p>Lors de l&amp;rsquo;évaluation de la complexité des algorithmes pour le décryptage (comme le crible algébrique), la connaissance de la distribution des nombres premiers est indispensable. De nombreux algorithmes de factorisation dépendent de la distribution des « nombres friables (Smooth numbers : nombres qui n&amp;rsquo;ont que de petits facteurs premiers) ».&lt;/p>
&lt;p>Pour évaluer rigoureusement la fréquence d&amp;rsquo;apparition des nombres friables, une compréhension profonde de la distribution des nombres premiers est requise, et ici aussi, des techniques de théorie analytique des nombres directement liées à la fonction zêta et à l&amp;rsquo;hypothèse de Riemann sont pleinement utilisées. Si l&amp;rsquo;hypothèse de Riemann est prouvée et que l&amp;rsquo;erreur de la distribution des nombres premiers est complètement déterminée, il sera possible d&amp;rsquo;évaluer plus précisément les limites de performance des algorithmes de factorisation.&lt;/p>
&lt;hr>
&lt;h1 id="8-si-lhypothèse-de-riemann-est-prouvée-la-cryptographie-sera-t-elle-cassée-">8. Si l&amp;rsquo;hypothèse de Riemann est prouvée, la cryptographie sera-t-elle cassée ?
&lt;/h1>&lt;p>On dit parfois comme une légende urbaine que « si l&amp;rsquo;hypothèse de Riemann est résolue, le chiffrement RSA s&amp;rsquo;effondrera en un instant », mais &lt;strong>c&amp;rsquo;est mathématiquement inexact&lt;/strong>.&lt;/p>
&lt;p>La preuve de l&amp;rsquo;hypothèse de Riemann elle-même ne créera pas immédiatement un algorithme magique qui accélère considérablement la factorisation. L&amp;rsquo;hypothèse de Riemann n&amp;rsquo;est qu&amp;rsquo;un théorème sur la « régularité de la distribution macroscopique » des nombres premiers, et elle ne nous dit pas directement par quels nombres premiers un nombre individuel $N$ est divisible (propriété locale).&lt;/p>
&lt;p>Cependant, l&amp;rsquo;impact n&amp;rsquo;est pas nul.
Il est extrêmement probable que de &lt;strong>« nouveaux outils mathématiques » et des « méthodes analytiques inconnues » soient découverts&lt;/strong> au cours du processus de démonstration de l&amp;rsquo;hypothèse de Riemann. L&amp;rsquo;histoire montre que lorsque le dernier théorème de Fermat et la conjecture de Poincaré ont été prouvés, les nouvelles théories développées au cours du processus ont fait progresser les mathématiques dans leur ensemble.&lt;/p>
&lt;p>Si des méthodes géométriques algébriques inconnues ou des méthodes géométriques non commutatives permettant de manipuler complètement les propriétés des zéros de la fonction zêta de Riemann sont établies, il n&amp;rsquo;est pas exclu que cela conduise à la découverte d&amp;rsquo;un algorithme révolutionnaire de factorisation (par exemple, un algorithme classique qui réduit la complexité au temps polynomial). En ce sens, les cryptographes ne peuvent jamais quitter des yeux les développements de l&amp;rsquo;hypothèse de Riemann.&lt;/p>
&lt;h3 id="ordinateurs-quantiques-et-algorithme-de-shor">Ordinateurs quantiques et algorithme de Shor
&lt;/h3>&lt;p>Une menace plus directe et réaliste pour la cryptographie n&amp;rsquo;est pas la preuve de l&amp;rsquo;hypothèse de Riemann, mais les &lt;strong>ordinateurs quantiques&lt;/strong>. « L&amp;rsquo;algorithme de Shor » publié par Peter Shor en 1994 a prouvé qu&amp;rsquo;avec un ordinateur quantique suffisamment performant, la factorisation peut être résolue en temps polynomial. Cela casserait fondamentalement le chiffrement RSA et la cryptographie sur les courbes elliptiques.&lt;/p>
&lt;p>Actuellement, une transition vers la « cryptographie post-quantique (Post-Quantum Cryptography, PQC) » (comme la cryptographie fondée sur les réseaux) qui ne peut pas être déchiffrée même par des ordinateurs quantiques progresse dans le monde entier. Les technologies de cryptographie basées sur les nombres premiers peuvent en un sens atteindre la fin de leur âge d&amp;rsquo;or, mais la valeur mathématique des nombres premiers eux-mêmes ne sera jamais perdue.&lt;/p>
&lt;hr>
&lt;h1 id="9-conclusion--lintersection-de-labstraction-mathématique-et-de-la-société-réelle">9. Conclusion : L&amp;rsquo;intersection de l&amp;rsquo;abstraction mathématique et de la société réelle
&lt;/h1>&lt;div class="mermaid">graph TD
A["Exploration des mathématiques pures"] --> B["Élucidation de l'hypothèse de Riemann"]
B --> C["Compréhension complète de la distribution des nombres premiers"]
C --> D["Développement spectaculaire de la théorie des nombres et de la géométrie algébrique"]
D -.-> E["Possibilité de nouveaux algorithmes de factorisation"]
E -.-> F["Mise à jour de l'évaluation de la sécurité cryptographique"]
A --> G["Mathématiques appliquées et informatique"]
G --> H["Efficacité des tests de primalité et de la génération cryptographique"]
H --> F&lt;/div>
&lt;p>La quête insatiable des nombres premiers, qui se poursuit depuis la Grèce antique, a été sublimée par le génie de Riemann en une magnifique symphonie sur le plan complexe (les zéros de la fonction zêta). Et étonnamment, ce cristal pur et immaculé des mathématiques est appliqué des siècles plus tard comme le bouclier le plus puissant garantissant la sécurité de la société de l&amp;rsquo;information.&lt;/p>
&lt;p>L&amp;rsquo;hypothèse de Riemann est une entité qui symbolise à la fois la « beauté abstraite » des mathématiques et sa « stupéfiante applicabilité au monde physique et à la société réelle ».&lt;/p>
&lt;p>Lorsqu&amp;rsquo;un jour cette immense montagne mathématique, dont personne n&amp;rsquo;a encore atteint le sommet, sera conquise, nous comprendrons parfaitement la vérité cosmique des nombres premiers et acquerrons une nouvelle perspective sur les fondements de la société de l&amp;rsquo;information. L&amp;rsquo;étude de la cryptographie est aussi un voyage à travers l&amp;rsquo;histoire de la sagesse humaine.&lt;/p></description></item><item><title>Histoire de la cryptographie : du chiffre de César à la cryptographie post-quantique (PQC)</title><link>http://kenji.blog/fr/p/history-of-cryptography-caesar-to-pqc/</link><pubDate>Fri, 11 Sep 2026 15:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/history-of-cryptography-caesar-to-pqc/</guid><description>&lt;img src="http://kenji.blog/p/history-of-cryptography-caesar-to-pqc/img/eyecatch.jpg" alt="Featured image of post Histoire de la cryptographie : du chiffre de César à la cryptographie post-quantique (PQC)" />&lt;h1 id="1-introduction--quest-ce-que-la-cryptographie-">1. Introduction : Qu&amp;rsquo;est-ce que la cryptographie ?
&lt;/h1>&lt;p>La cryptographie (Cryptography) est la technologie permettant de préserver la confidentialité des informations, et a évolué avec l&amp;rsquo;histoire de l&amp;rsquo;humanité. De la transmission d&amp;rsquo;ordres secrets lors des guerres antiques à la protection des informations de cartes de crédit sur l&amp;rsquo;Internet moderne, le but de la cryptographie est resté le même. Il s&amp;rsquo;agit de « s&amp;rsquo;assurer que seul le destinataire prévu peut comprendre l&amp;rsquo;information, et qu&amp;rsquo;elle ne peut pas être déchiffrée par des tiers ».&lt;/p>
&lt;p>Dans la sécurité de l&amp;rsquo;information moderne, la cryptographie ne se limite pas à la simple « dissimulation de l&amp;rsquo;information (Confidentialité) », mais joue également un rôle important dans l&amp;rsquo;« Intégrité (Integrity) » des données, l&amp;rsquo;« Authentification (Authentication) », et la « Non-répudiation (Non-repudiation) ».&lt;/p>
&lt;p>Cet article retrace en détail l&amp;rsquo;histoire de l&amp;rsquo;évolution de la cryptographie d&amp;rsquo;un point de vue technologique et mathématique, en commençant par les simples chiffrements par substitution de l&amp;rsquo;Antiquité, en passant par les chiffrements mécaniques, la cryptographie moderne à clé symétrique et publique, jusqu&amp;rsquo;à l&amp;rsquo;ère de la « Cryptographie Post-Quantique (PQC) » provoquée par l&amp;rsquo;utilisation pratique des ordinateurs quantiques.&lt;/p>
&lt;hr>
&lt;h1 id="2-lère-de-la-cryptographie-classique--substitution-et-transposition-de-caractères">2. L&amp;rsquo;ère de la cryptographie classique : Substitution et transposition de caractères
&lt;/h1>&lt;p>Les origines de la cryptographie remontent avant notre ère. Les premiers chiffrements étaient principalement composés de deux approches : « transposition (réarrangement) » et « substitution (remplacement) ».&lt;/p>
&lt;h2 id="le-chiffre-de-la-scytale-chiffrement-par-transposition">Le chiffre de la scytale (Chiffrement par transposition)
&lt;/h2>&lt;p>Utilisée à Sparte, dans la Grèce antique, au Ve siècle av. J.-C., la « Scytale » est l&amp;rsquo;un des plus anciens dispositifs cryptographiques. Une longue et étroite bande de parchemin est enroulée autour d&amp;rsquo;un bâton de bois d&amp;rsquo;une épaisseur spécifique, et un message y est écrit horizontalement. Lorsque le parchemin est déroulé, les caractères apparaissent dans un ordre dénué de sens, mais un destinataire ayant un bâton de la même épaisseur peut enrouler le parchemin à nouveau pour lire le message original.&lt;/p>
&lt;h2 id="le-chiffre-de-césar-chiffrement-par-substitution-monoalphabétique">Le chiffre de César (Chiffrement par substitution monoalphabétique)
&lt;/h2>&lt;p>Au 1er siècle av. J.-C., le héros de la Rome antique Jules César aurait utilisé le « chiffre de César ». Il s&amp;rsquo;agit d&amp;rsquo;un chiffrement par substitution monoalphabétique (Monoalphabetic substitution) qui décale l&amp;rsquo;alphabet d&amp;rsquo;un certain nombre (généralement 3 caractères).&lt;/p>
&lt;p>Mathématiquement, en traitant les lettres comme des nombres de $0$ à $25$ et le nombre de décalages comme $K$, la conversion du texte clair $P$ en texte chiffré $C$ est exprimée par la congruence suivante :&lt;/p>
$$C \equiv P + K \pmod{26}$$
&lt;p>Le déchiffrement effectue l&amp;rsquo;opération inverse :&lt;/p>
$$P \equiv C - K \pmod{26}$$
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Exemple simple d&amp;#39;implémentation du chiffre de César en Python&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">mode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;encrypt&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">mode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;decrypt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shift&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">shift&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isalpha&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;A&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isupper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calcul du décalage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="nb">chr&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">base&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">26&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">char&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Exemple d&amp;#39;exécution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plaintext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;HELLO WORLD&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plaintext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;encrypt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Texte chiffré : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># KHOOR ZRUOG&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="analyse-fréquentielle-et-le-chiffre-de-vigenère">Analyse fréquentielle et le chiffre de Vigenère
&lt;/h2>&lt;p>Les chiffrements par substitution monoalphabétique ont été facilement déchiffrés grâce à l&amp;rsquo;« Analyse Fréquentielle (Frequency Analysis) » conçue par le savant arabe du 9ème siècle Al-Kindi. Elle utilise les propriétés statistiques de la langue, comme le fait que « E » et « T » apparaissent fréquemment en anglais.&lt;/p>
&lt;p>Pour contrer cela, le « chiffre de Vigenère (Vigenère cipher) » a été inventé au 16ème siècle. Il s&amp;rsquo;agit d&amp;rsquo;un chiffrement par substitution polyalphabétique (Polyalphabetic substitution) qui utilise plusieurs décalages (clés) de manière périodique, et a été appelé « Le Chiffre Indéchiffrable » pendant environ 300 ans.&lt;/p>
&lt;p>Mathématiquement, le $i$-ème caractère $P_i$ du texte clair et le $i$-ème caractère $K_i$ de la clé répétée sont utilisés pour chiffrer comme suit :&lt;/p>
$$C_i \equiv P_i + K_i \pmod{26}$$
&lt;p>Ce chiffrement a également été déchiffré au 19ème siècle par Charles Babbage et Friedrich Kasiski, qui ont découvert la « méthode de Kasiski (Kasiski examination) », permettant de déduire la longueur de la clé à partir de motifs répétitifs dans le texte chiffré.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Classification de la cryptographie classique"
A["Cryptographie classique"] --> B["Chiffrement par transposition"]
A --> C["Chiffrement par substitution"]
B --> D["Chiffrement Scytale"]
C --> E["Substitution monoalphabétique"]
C --> F["Substitution polyalphabétique"]
E --> G["Chiffre de César"]
F --> H["Chiffre de Vigenère"]
end&lt;/div>
&lt;hr>
&lt;h1 id="3-cryptographie-mécanique-et-guerres-mondiales--enigma-et-son-déchiffrement">3. Cryptographie mécanique et guerres mondiales : Enigma et son déchiffrement
&lt;/h1>&lt;p>Au 20ème siècle, alors que les moyens de communication passaient des lettres au télégraphe et à la radio, la vitesse et la complexité du chiffrement sont devenues nécessaires. C&amp;rsquo;est là que la « cryptographie mécanique », combinant des rotors (disques rotatifs), est apparue.&lt;/p>
&lt;h2 id="la-menace-denigma">La menace d&amp;rsquo;Enigma
&lt;/h2>&lt;p>Pendant la Seconde Guerre mondiale, l&amp;rsquo;« Enigma », utilisée par l&amp;rsquo;Allemagne nazie, est la machine de chiffrement la plus célèbre de l&amp;rsquo;histoire de la cryptographie. Enigma était composée de plusieurs rotors (généralement 3 à 4), d&amp;rsquo;un tableau de connexions (Steckerbrett) qui échangeait le câblage des lettres, et d&amp;rsquo;un réflecteur (rotor d&amp;rsquo;inversion).&lt;/p>
&lt;p>Le rotor tournant chaque fois qu&amp;rsquo;une lettre était tapée sur le clavier, taper la même lettre de suite produirait des caractères chiffrés différents (le summum du chiffrement polyalphabétique). Son espace de clés (combinaisons de paramètres) atteignait environ $1.58 \times 10^{19}$ (environ 15,8 quintillions), ce qui rendait le déchiffrement par force brute impossible avec la technologie de l&amp;rsquo;époque.&lt;/p>
&lt;h2 id="alan-turing-et-la--bombe-">Alan Turing et la « Bombe »
&lt;/h2>&lt;p>L&amp;rsquo;équipe de cryptanalyse de Bletchley Park en Grande-Bretagne a relevé le défi de cette imprenable Enigma, en s&amp;rsquo;appuyant sur les travaux initiaux de mathématiciens polonais comme Marian Rejewski.&lt;/p>
&lt;p>En particulier, Alan Turing a développé la « Bombe », une machine de déchiffrement électromécanique, en utilisant des suppositions de texte clair (Cribs) correspondant à des parties du texte chiffré. La Bombe détectait rapidement les contradictions logiques et éliminait un par un les paramètres de rotor impossibles, réussissant ainsi à déchiffrer Enigma. On dit que cet exploit a avancé la victoire des Alliés de plusieurs années.&lt;/p>
&lt;hr>
&lt;h1 id="4-laube-de-la-cryptographie-moderne--cryptographie-à-clé-symétrique-des-et-aes">4. L&amp;rsquo;aube de la cryptographie moderne : Cryptographie à clé symétrique (DES et AES)
&lt;/h1>&lt;p>Après la guerre, avec l&amp;rsquo;avènement des ordinateurs, la cryptographie a subi un changement de paradigme radical, passant de la manipulation de « caractères » à la manipulation de « bits (0 et 1) ».&lt;/p>
&lt;h2 id="claude-shannon-et-la-théorie-de-linformation">Claude Shannon et la théorie de l&amp;rsquo;information
&lt;/h2>&lt;p>En 1949, Claude Shannon a publié l&amp;rsquo;article « Communication Theory of Secrecy Systems », jetant les bases mathématiques de la cryptographie moderne. Il a proposé la « Confusion (Confusion) » et la « Diffusion (Diffusion) » comme principes pour la conception de chiffrements sécurisés.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Confusion&lt;/strong> : Rendre la relation entre la clé et le texte chiffré aussi complexe que possible. (Réalisé par substitution / boîtes S)&lt;/li>
&lt;li>&lt;strong>Diffusion&lt;/strong> : S&amp;rsquo;assurer que la modification d&amp;rsquo;un seul bit du texte clair affecte de nombreux bits du texte chiffré. (Réalisé par transposition / permutation)&lt;/li>
&lt;/ul>
&lt;h2 id="des-data-encryption-standard">DES (Data Encryption Standard)
&lt;/h2>&lt;p>En 1977, le National Institute of Standards and Technology américain (NIST, alors NBS) a établi « DES », basé sur un design d&amp;rsquo;IBM, comme chiffrement standard.
DES utilise une architecture appelée « Réseau de Feistel (Feistel Network) » et a une taille de bloc de 64 bits et une longueur de clé de 56 bits. Il avait l&amp;rsquo;avantage d&amp;rsquo;implémentation que les algorithmes de chiffrement et de déchiffrement avaient presque la même structure.&lt;/p>
&lt;p>Cependant, à mesure que la puissance de calcul des ordinateurs augmentait, il est devenu évident qu&amp;rsquo;une longueur de clé de 56 bits (environ $7.2 \times 10^{16}$ combinaisons) était insuffisante. En 1998, l&amp;rsquo;Electronic Frontier Foundation (EFF) a développé une machine dédiée « Deep Crack » et a déchiffré DES en quelques jours.&lt;/p>
&lt;h2 id="aes-advanced-encryption-standard">AES (Advanced Encryption Standard)
&lt;/h2>&lt;p>Comme nouveau standard pour remplacer DES, « AES » a été établi en 2001. L&amp;rsquo;algorithme « Rijndael », conçu par des cryptographes belges et sélectionné par appel d&amp;rsquo;offres public, a été adopté.&lt;/p>
&lt;p>AES adopte une « structure SPN (Substitution-Permutation Network) » au lieu d&amp;rsquo;une structure de Feistel, et utilise des opérations mathématiques sur le corps de Galois (corps fini) $GF(2^8)$. La longueur de la clé peut être choisie parmi 128, 192 ou 256 bits, et il est encore largement utilisé dans le monde aujourd&amp;rsquo;hui comme cryptographie à clé symétrique standard.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Traitement d'un tour de AES (Structure SPN)"
A["État d'entrée (128-bit)"] --> B("SubBytes (Substitution d'octets / S-Box)")
B --> C("ShiftRows (Décalage de lignes)")
C --> D("MixColumns (Mélange de colonnes / Multiplication sur GF(2^8))")
D --> E("AddRoundKey (XOR avec la clé de tour)")
E --> F["Au tour suivant"]
end&lt;/div>
&lt;hr>
&lt;h1 id="5-la-révolution-de-la-cryptographie-à-clé-publique--de-diffie-hellman-à-rsa">5. La révolution de la cryptographie à clé publique : de Diffie-Hellman à RSA
&lt;/h1>&lt;p>La cryptographie à clé symétrique avait une faiblesse fatale. C&amp;rsquo;était le « Problème de distribution de clés (Key Distribution Problem) ». C&amp;rsquo;est la question de savoir comment partager en toute sécurité une « clé commune » avec une partie distante avant de commencer la communication chiffrée. Ce problème a été résolu par la « cryptographie à clé publique », née dans les années 1970.&lt;/p>
&lt;h2 id="léchange-de-clés-diffie-hellman">L&amp;rsquo;échange de clés Diffie-Hellman
&lt;/h2>&lt;p>En 1976, Whitfield Diffie et Martin Hellman ont publié l&amp;rsquo;article révolutionnaire « New Directions in Cryptography ». Ils ont proposé une méthode permettant de partager des clés en toute sécurité, même sur un canal de communication écouté, en utilisant la difficulté mathématique du « Problème du logarithme discret (Discrete Logarithm Problem) ».&lt;/p>
&lt;ol>
&lt;li>Un grand nombre premier $p$ et un générateur $g$ sont rendus publics.&lt;/li>
&lt;li>Alice choisit une valeur secrète $a$ et envoie $A = g^a \pmod{p}$ à Bob.&lt;/li>
&lt;li>Bob choisit une valeur secrète $b$ et envoie $B = g^b \pmod{p}$ à Alice.&lt;/li>
&lt;li>Alice calcule $K = B^a \pmod{p}$, et Bob calcule $K = A^b \pmod{p}$.&lt;/li>
&lt;li>Par les lois des exposants, $K = (g^b)^a = (g^a)^b = g^{ab} \pmod{p}$, réussissant ainsi à partager la même clé $K$.&lt;/li>
&lt;/ol>
&lt;h2 id="le-chiffrement-rsa">Le chiffrement RSA
&lt;/h2>&lt;p>L&amp;rsquo;année suivante, en 1977, le « chiffrement RSA » a été conçu par Ron Rivest, Adi Shamir et Leonard Adleman. Il est basé sur la propriété qu&amp;rsquo;« il est difficile de factoriser en nombres premiers d&amp;rsquo;énormes nombres composés ».&lt;/p>
&lt;p>&lt;strong>Mécanisme mathématique de RSA :&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Choisissez deux énormes nombres premiers $p$ et $q$, et calculez $n = p \times q$.&lt;/li>
&lt;li>Calculez l&amp;rsquo;indicatrice d&amp;rsquo;Euler $\phi(n) = (p-1)(q-1)$.&lt;/li>
&lt;li>Choisissez un entier $e$ (clé publique) premier avec $\phi(n)$.&lt;/li>
&lt;li>Calculez un entier $d$ (clé privée) tel que $e \times d \equiv 1 \pmod{\phi(n)}$.&lt;/li>
&lt;/ol>
&lt;p>Chiffrement : Pour le texte clair $M$, $C \equiv M^e \pmod{n}$
Déchiffrement : Pour le texte chiffré $C$, $M \equiv C^d \pmod{n}$&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Code Python illustrant le concept du chiffrement RSA (pas pour une utilisation pratique)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calcul de l&amp;#39;inverse modulaire par l&amp;#39;algorithme d&amp;#39;Euclide étendu&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">g&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">rsa_example&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Exemple utilisant de petits nombres premiers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">61&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">53&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">17&lt;/span> &lt;span class="c1"># Valeur première avec phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">d&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">d&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Clé publique : (e=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Clé privée : (d=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Chiffrement et déchiffrement d&amp;#39;un message&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">65&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Texte clair : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; Texte chiffré : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; Après déchiffrement : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">rsa_example&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="6-lessor-de-la-cryptographie-sur-les-courbes-elliptiques-ecc">6. L&amp;rsquo;essor de la cryptographie sur les courbes elliptiques (ECC)
&lt;/h1>&lt;p>Le chiffrement RSA est puissant, mais à mesure que les performances des ordinateurs s&amp;rsquo;améliorent, il est devenu nécessaire d&amp;rsquo;augmenter la longueur de la clé (actuellement 2048 bits ou 3072 bits) pour maintenir la sécurité, ce qui a entraîné le problème de l&amp;rsquo;augmentation des coûts de calcul.&lt;/p>
&lt;p>Ainsi, la « Cryptographie sur les courbes elliptiques (Elliptic Curve Cryptography : ECC) » a été proposée en 1985. Elle utilise l&amp;rsquo;addition de points sur une courbe elliptique (généralement de la forme $y^2 = x^3 + ax + b$) sur un corps fini.&lt;/p>
&lt;p>Le problème du logarithme discret sur courbe elliptique (ECDLP) est connu pour être encore plus difficile à résoudre que le problème de factorisation en nombres premiers, et &lt;strong>la sécurité équivalente à 3072 bits pour RSA peut être atteinte avec une longueur de clé de seulement 256 bits pour ECC&lt;/strong>. Cela a rendu possible une communication chiffrée rapide et sécurisée (comme ECDSA et ECDH) même dans des environnements avec des ressources de calcul limitées, comme les smartphones et les appareils IoT.&lt;/p>
&lt;hr>
&lt;h1 id="7-la-menace-des-ordinateurs-quantiques-et-la-cryptographie-post-quantique-pqc">7. La menace des ordinateurs quantiques et la cryptographie post-quantique (PQC)
&lt;/h1>&lt;p>La technologie cryptographique semblait solide comme un roc, mais l&amp;rsquo;algorithme de Shor (« Shor&amp;rsquo;s algorithm ») publié par Peter Shor en 1994 a provoqué une onde de choc.&lt;/p>
&lt;p>Les ordinateurs quantiques effectuent des calculs en utilisant les propriétés de la mécanique quantique que sont la « superposition » et l&amp;rsquo;« intrication quantique ». Il a été mathématiquement prouvé que l&amp;rsquo;exécution de l&amp;rsquo;algorithme de Shor sur un ordinateur quantique suffisamment performant pourrait résoudre le problème de factorisation en nombres premiers et le problème du logarithme discret en « temps polynomial ». En d&amp;rsquo;autres termes, le jour où un ordinateur quantique pratique sera achevé (Q-Day), toute la cryptographie à clé publique actuellement utilisée, comme RSA et ECC, s&amp;rsquo;effondrera instantanément.&lt;/p>
&lt;h2 id="lémergence-de-la-pqc-post-quantum-cryptography">L&amp;rsquo;émergence de la PQC (Post-Quantum Cryptography)
&lt;/h2>&lt;p>Pour se préparer à cette menace sans précédent, la recherche sur la « Cryptographie Post-Quantique (PQC) », basée sur de nouveaux problèmes mathématiques difficiles à déchiffrer même pour les ordinateurs quantiques, progresse rapidement. Le NIST (National Institute of Standards and Technology des États-Unis) mène un processus de normalisation de la PQC depuis de nombreuses années, et les approches mathématiques suivantes sont considérées comme les plus prometteuses :&lt;/p>
&lt;h3 id="1-cryptographie-basée-sur-les-réseaux-euclidiens-lattice-based-cryptography">1. Cryptographie basée sur les réseaux euclidiens (Lattice-based Cryptography)
&lt;/h3>&lt;p>C&amp;rsquo;est actuellement l&amp;rsquo;approche la plus prometteuse et elle a été adoptée pour les algorithmes de normalisation du NIST (ML-KEM / Kyber, ML-DSA / Dilithium). Elle est basée sur la difficulté de trouver un point spécifique sur un « réseau (Lattice) » dans un espace multidimensionnel (comme le problème du plus court vecteur : SVP) et sur le problème LWE (Learning With Errors).&lt;/p>
&lt;p>Le concept du problème LWE utilise la propriété que si un « petit bruit (erreur) » est intentionnellement ajouté à un système d&amp;rsquo;équations linéaires, il devient soudainement très difficile de trouver la solution.
Système d&amp;rsquo;équations : $\mathbf{A}\mathbf{s} + \mathbf{e} \equiv \mathbf{b} \pmod{q}$
($\mathbf{A}$ et $\mathbf{b}$ sont publics, $\mathbf{s}$ est la clé privée, $\mathbf{e}$ est le petit bruit)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Pseudo-code conceptuel du problème LWE (à des fins d&amp;#39;apprentissage)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span> &lt;span class="c1"># Dimension&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3329&lt;/span> &lt;span class="c1"># Modulo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">512&lt;/span> &lt;span class="c1"># Nombre d&amp;#39;équations&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Clé secrète s et petite erreur e&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Matrice publique A et vecteur public b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">A&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Même en utilisant un ordinateur quantique, il est considéré comme très difficile de récupérer s à partir de A et b&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="2-cryptographie-basée-sur-le-hachage-hash-based-cryptography">2. Cryptographie basée sur le hachage (Hash-based Cryptography)
&lt;/h3>&lt;p>Il s&amp;rsquo;agit d&amp;rsquo;un système de signature numérique qui fonde sa sécurité uniquement sur la résistance aux collisions des fonctions de hachage. Comme il n&amp;rsquo;a pas de structure mathématique, il résiste aux attaques quantiques, mais la taille de la signature a tendance à être importante (comme SPHINCS+).&lt;/p>
&lt;h3 id="3-cryptographie-basée-sur-les-codes-code-based-cryptography">3. Cryptographie basée sur les codes (Code-based Cryptography)
&lt;/h3>&lt;p>Il s&amp;rsquo;agit d&amp;rsquo;un système de chiffrement basé sur la théorie des codes correcteurs d&amp;rsquo;erreurs. Le chiffrement de McEliece, proposé en 1978, est célèbre, a une longue histoire et une réputation de sécurité établie, mais son défi est que la taille de la clé publique est extrêmement grande (parfois de plusieurs mégaoctets).&lt;/p>
&lt;div class="mermaid">timeline
title "Histoire de l'évolution de la cryptographie et de l'informatique"
"Antiquité - Moyen Âge" : "Chiffre de César" : "Chiffre de Vigenère" : "Naissance de l'analyse fréquentielle"
"Années 1930 - 40" : "Opération et déchiffrement d'Enigma" : "Développement de la machine de Turing / Bombe"
"Années 1970" : "Standardisation de DES (1977)" : "Échange de clés Diffie-Hellman (1976)" : "Naissance du chiffrement RSA (1977)"
"Années 1980 - 90" : "Proposition de la cryptographie sur les courbes elliptiques (ECC)" : "Publication de l'algorithme de Shor (1994)"
"Années 2000" : "Standardisation de AES (2001)"
"Années 2010 - Présent" : "Accélération de la recherche sur les ordinateurs quantiques" : "Début du projet de standardisation PQC par le NIST"
"Futur proche (Q-Day)" : "Réalisation d'ordinateurs quantiques à grande échelle ?" : "Transition complète vers PQC (ML-KEM/ML-DSA)"&lt;/div>
&lt;hr>
&lt;h1 id="8-conclusion--une-bataille-sans-fin-entre-le-bouclier-et-la-lance">8. Conclusion : Une bataille sans fin entre le bouclier et la lance
&lt;/h1>&lt;p>L&amp;rsquo;histoire de la technologie cryptographique est l&amp;rsquo;histoire d&amp;rsquo;une bataille sans fin entre l&amp;rsquo;invention de nouvelles méthodes de chiffrement (le bouclier) et de nouvelles méthodes de déchiffrement (la lance) pour les percer.&lt;/p>
&lt;p>Le chiffre de César a été vaincu par l&amp;rsquo;analyse fréquentielle, et l&amp;rsquo;Enigma prétendument invincible a été vaincue par le génie de Turing et la puissance de la machine. Et aujourd&amp;rsquo;hui, les chiffrements puissants comme RSA et ECC qui soutiennent les fondements de la société Internet moderne sont menacés par une nouvelle « lance », l&amp;rsquo;ordinateur quantique.&lt;/p>
&lt;p>Cependant, l&amp;rsquo;humanité regarde déjà vers l&amp;rsquo;avenir, et se prépare à un nouveau « bouclier » appelé cryptographie post-quantique (PQC). Actuellement, dans les infrastructures informatiques du monde entier, la préparation à la transition de la cryptographie à clé publique existante vers la PQC (garantir la crypto-agilité) est une question urgente.&lt;/p>
&lt;p>La cryptographie n&amp;rsquo;est pas seulement un puzzle mathématique difficile, mais la barrière la plus solide pour protéger notre vie privée, nos biens, et l&amp;rsquo;infrastructure sociale elle-même.&lt;/p></description></item><item><title>【Explication mathématique】Le fonctionnement de la cryptographie RSA expliqué aux lycéens</title><link>http://kenji.blog/fr/p/rsa-encryption-math-explained-for-beginners/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/rsa-encryption-math-explained-for-beginners/</guid><description>&lt;img src="http://kenji.blog/p/rsa-encryption-math-explained-for-beginners/img/eyecatch.jpg" alt="Featured image of post 【Explication mathématique】Le fonctionnement de la cryptographie RSA expliqué aux lycéens" />&lt;p>L&amp;rsquo;une des technologies qui soutient fondamentalement la sécurité de la société Internet est la « cryptographie RSA ». La plupart des communications que nous utilisons négligemment chaque jour, telles que les paiements par carte de crédit lors des achats en ligne, les échanges sur les réseaux sociaux avec des amis, ou l&amp;rsquo;envoi et la réception d&amp;rsquo;informations confidentielles d&amp;rsquo;entreprise, sont protégées par cette cryptographie RSA ou par ses technologies successives.&lt;/p>
&lt;p>Cependant, lorsque l&amp;rsquo;on entend le mot « cryptographie », on peut imaginer des machines de chiffrement complexes comme celles des films d&amp;rsquo;espionnage, ou des mathématiques super avancées que seuls quelques génies peuvent comprendre. S&amp;rsquo;il est vrai que la théorie cryptographique moderne repose sur des mathématiques avancées, &lt;strong>le mécanisme fondamental de la cryptographie RSA peut être pleinement compris avec des connaissances mathématiques acquises au lycée (propriétés des entiers, nombres premiers, congruences, etc.)&lt;/strong>.&lt;/p>
&lt;p>Dans cet article, en partant des connaissances mathématiques du lycée, nous expliquerons étape par étape et de manière exhaustive les principes mathématiques sur lesquels repose la cryptographie RSA et pourquoi son décryptage est si difficile. Nous l&amp;rsquo;expliquerons soigneusement avec des exemples concrets pour que même ceux qui ne sont pas très à l&amp;rsquo;aise avec les mathématiques puissent comprendre.&lt;/p>
&lt;hr>
&lt;h2 id="1-cryptographie-à-clé-symétrique-et-cryptographie-à-clé-publique">1. Cryptographie à clé symétrique et cryptographie à clé publique
&lt;/h2>&lt;p>Avant d&amp;rsquo;aborder le mécanisme mathématique de la cryptographie RSA, passons d&amp;rsquo;abord en revue les concepts de base de la cryptographie. Les méthodes de chiffrement sont généralement divisées en deux types : la « cryptographie à clé symétrique » (ou clé secrète) et la « cryptographie à clé publique ».&lt;/p>
&lt;h3 id="11-les-limites-de-la-cryptographie-à-clé-symétrique">1.1 Les limites de la cryptographie à clé symétrique
&lt;/h3>&lt;p>La plupart des cryptographies utilisées depuis l&amp;rsquo;Antiquité sont appelées « cryptographie à clé symétrique ». C&amp;rsquo;est une méthode où &lt;strong>la même clé est utilisée pour le « chiffrement (conversion du message en un texte chiffré secret) » et le « déchiffrement (restauration du texte chiffré en son message d&amp;rsquo;origine) »&lt;/strong>.&lt;/p>
&lt;p>Par exemple, supposons qu&amp;rsquo;Alice veuille envoyer une lettre secrète à Bob. Alice met la lettre dans une boîte et la verrouille à l&amp;rsquo;aide d&amp;rsquo;un cadenas (clé symétrique). Pour que Bob puisse ouvrir cette boîte, il doit posséder la même clé que celle utilisée par Alice.&lt;/p>
&lt;p>Cette méthode pose un problème majeur : le « problème de distribution des clés ». Lorsque Alice et Bob, éloignés l&amp;rsquo;un de l&amp;rsquo;autre, communiquent pour la première fois, comment peuvent-ils partager la clé sans être sur écoute ? Si la clé est volée par un tiers pendant son envoi par la poste, toutes les communications chiffrées ultérieures seront complètement compromises.&lt;/p>
&lt;h3 id="12-linvention-révolutionnaire--la--cryptographie-à-clé-publique-">1.2 L&amp;rsquo;invention révolutionnaire : la « Cryptographie à clé publique »
&lt;/h3>&lt;p>La « cryptographie à clé publique » a été inventée pour résoudre ce problème de distribution des clés. La cryptographie RSA en est un type.&lt;/p>
&lt;p>Dans la cryptographie à clé publique, &lt;strong>deux clés différentes sont utilisées : une « clé pour chiffrer (clé publique) » et une « clé pour déchiffrer (clé privée) »&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Le destinataire, Bob, crée une paire composée d&amp;rsquo;une « clé publique » et d&amp;rsquo;une « clé privée ».&lt;/li>
&lt;li>Bob publie la « clé publique » dans le monde entier (peu importe qui l&amp;rsquo;obtient).&lt;/li>
&lt;li>L&amp;rsquo;expéditrice, Alice, utilise la « clé publique » de Bob pour chiffrer son message et l&amp;rsquo;envoie.&lt;/li>
&lt;li>Le message chiffré ne peut être déchiffré qu&amp;rsquo;avec la « clé privée », que seul Bob possède.&lt;/li>
&lt;/ol>
&lt;p>Si l&amp;rsquo;on compare cela à un cadenas, Bob fabrique de nombreux « cadenas ouverts (clés publiques) » et les disperse à travers le monde. Alice place un message destiné à Bob dans une boîte et la verrouille avec un cadenas de Bob qu&amp;rsquo;elle a trouvé. Une fois fermé, le cadenas ne peut être ouvert qu&amp;rsquo;avec la « clé passe-partout (clé privée) » détenue par Bob. Même si quelqu&amp;rsquo;un vole la boîte en cours de route, il ne peut pas l&amp;rsquo;ouvrir sans la clé passe-partout.&lt;/p>
&lt;div class="mermaid">graph TD
A["Alice (Expéditrice)"] --> B["Texte clair (Message)"]
B --> C["Processus de chiffrement"]
D["Clé publique de Bob (Accessible à tous)"] --> C
C --> E["Transmission via Internet : Texte chiffré"]
E --> F["Processus de déchiffrement"]
G["Clé privée de Bob (Détenue uniquement par Bob)"] --> F
F --> H["Texte clair restauré (Message)"]
H --> I["Bob (Destinataire)"]&lt;/div>
&lt;p>Pour réaliser ce système révolutionnaire, une sorte de &lt;strong>« fonction à sens unique (un puzzle mathématique à sens unique) »&lt;/strong> est nécessaire : « un chiffrement facile avec la clé publique, mais un déchiffrement absolument impossible sans la clé privée ». C&amp;rsquo;est là que les « nombres premiers » que nous connaissons bien ont été choisis comme pièces de ce puzzle.&lt;/p>
&lt;hr>
&lt;h2 id="2-base-mathématique-de-la-cryptographie-rsa-1--nombres-premiers-et-décomposition-en-facteurs-premiers">2. Base mathématique de la cryptographie RSA 1 : Nombres premiers et décomposition en facteurs premiers
&lt;/h2>&lt;p>La sécurité de la cryptographie RSA repose sur le fait mathématique que &lt;strong>« la décomposition en facteurs premiers de nombres gigantesques est extrêmement difficile »&lt;/strong>.&lt;/p>
&lt;h3 id="21-quest-ce-quun-nombre-premier-">2.1 Qu&amp;rsquo;est-ce qu&amp;rsquo;un nombre premier ?
&lt;/h3>&lt;p>Un nombre premier est « un entier naturel supérieur à 1 qui ne peut être divisé de manière exacte que par 1 et par lui-même ».
Exemples : $2, 3, 5, 7, 11, 13, 17, 19, 23...$&lt;/p>
&lt;p>Les nombres premiers sont comme les « atomes » de tous les nombres entiers. Tout entier naturel peut être décomposé sous la forme d&amp;rsquo;une multiplication de nombres premiers. C&amp;rsquo;est ce qu&amp;rsquo;on appelle la &lt;strong>décomposition en facteurs premiers&lt;/strong>. Par exemple, $60 = 2^2 \times 3 \times 5$. Le fait que l&amp;rsquo;on puisse décomposer un nombre en facteurs premiers d&amp;rsquo;une seule et unique manière (si l&amp;rsquo;on ignore l&amp;rsquo;ordre) est connu sous le nom de « Théorème fondamental de l&amp;rsquo;arithmétique ».&lt;/p>
&lt;h3 id="22-la-difficulté-de-la-décomposition-en-facteurs-premiers-fonction-à-sens-unique">2.2 La difficulté de la décomposition en facteurs premiers (Fonction à sens unique)
&lt;/h3>&lt;p>Ce qui est important ici, c&amp;rsquo;est l&amp;rsquo;asymétrie selon laquelle &lt;strong>« la multiplication est facile, mais la décomposition en facteurs premiers est difficile »&lt;/strong>.&lt;/p>
&lt;p>Par exemple, essayez de calculer mentalement la multiplication des deux nombres premiers suivants.
$11 \times 13 = ?$
C&amp;rsquo;est facile. La réponse est $143$.&lt;/p>
&lt;p>Alors, qu&amp;rsquo;en est-il du nombre suivant ?
Décomposez $323$ en facteurs premiers.
Qu&amp;rsquo;en pensez-vous ? Cela devrait prendre un peu plus de temps. (La réponse est $17 \times 19$).&lt;/p>
&lt;p>Si les nombres sont petits, les humains peuvent s&amp;rsquo;en sortir d&amp;rsquo;une manière ou d&amp;rsquo;une autre, mais lorsque les nombres deviennent grands, les calculs deviennent explosivement difficiles, même avec des ordinateurs. Dans la cryptographie RSA principalement utilisée aujourd&amp;rsquo;hui, on utilise un nombre $N = p \times q$, qui est le produit de deux nombres premiers immenses, $p$ et $q$, de 2048 bits (environ 600 chiffres en base 10).&lt;/p>
&lt;p>Lorsqu&amp;rsquo;on donne deux immenses nombres premiers $p$ et $q$, un ordinateur peut calculer $N$ en un instant (moins d&amp;rsquo;une milliseconde). Cependant, à l&amp;rsquo;inverse, si l&amp;rsquo;on ne donne que $N$, trouver les $p$ et $q$ originaux prendrait tellement de temps que même les superordinateurs les plus rapides actuels ne pourraient pas le résoudre en le calculant pendant des milliers de milliards d&amp;rsquo;années.&lt;/p>
&lt;p>Cette &lt;strong>« asymétrie de calcul (l&amp;rsquo;aller est facile, le retour est difficile) »&lt;/strong> devient le fondement qui crée la relation entre la clé publique et la clé privée.&lt;/p>
&lt;hr>
&lt;h2 id="3-base-mathématique-de-la-cryptographie-rsa-2--congruence-arithmétique-modulaire">3. Base mathématique de la cryptographie RSA 2 : Congruence (Arithmétique modulaire)
&lt;/h2>&lt;p>Les calculs de la cryptographie RSA ne se font pas dans le monde des additions et multiplications où les nombres deviennent infiniment grands comme nous en avons l&amp;rsquo;habitude, mais dans le monde des « restes » après division par un certain nombre. C&amp;rsquo;est ce qu&amp;rsquo;on appelle la &lt;strong>congruence (ou arithmétique modulaire)&lt;/strong>.&lt;/p>
&lt;h3 id="31-les-mathématiques-de-lhorloge">3.1 Les mathématiques de l&amp;rsquo;horloge
&lt;/h3>&lt;p>L&amp;rsquo;arithmétique modulaire est souvent comparée aux « mathématiques de l&amp;rsquo;horloge ». S&amp;rsquo;il est 10 heures actuellement, quelle heure sera-t-il dans 5 heures ? $10 + 5 = 15$ heures, mais sur une horloge classique de 12 heures, on répond « 3 heures ». C&amp;rsquo;est parce que le reste de la division de 15 par 12 est 3.&lt;/p>
&lt;p>Dans le monde mathématique, on écrit cela comme suit :
&lt;/p>
$$ 15 \equiv 3 \pmod{12} $$
&lt;p>
Cela se lit « 15 est congru à 3 modulo 12 (le reste de la division par 12 est égal) ».&lt;/p>
&lt;h3 id="32-propriétés-fondamentales-des-congruences">3.2 Propriétés fondamentales des congruences
&lt;/h3>&lt;p>Les congruences ont des propriétés très pratiques qui ressemblent beaucoup à celles des équations ($=$). Soit $N$ le module (le diviseur).
Lorsque $a \equiv b \pmod N$ et $c \equiv d \pmod N$, ce qui suit est vrai :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition :&lt;/strong> $a + c \equiv b + d \pmod N$&lt;/li>
&lt;li>&lt;strong>Soustraction :&lt;/strong> $a - c \equiv b - d \pmod N$&lt;/li>
&lt;li>&lt;strong>Multiplication :&lt;/strong> $a \times c \equiv b \times d \pmod N$&lt;/li>
&lt;li>&lt;strong>Exponentiation (puissance) :&lt;/strong> $a^k \equiv b^k \pmod N$ ($k$ est un entier naturel)&lt;/li>
&lt;/ol>
&lt;p>La propriété d&amp;rsquo;« exponentiation » est particulièrement importante. Elle signifie que &lt;strong>« le reste d&amp;rsquo;une puissance est égal à la puissance du reste »&lt;/strong>.
Par exemple, supposons que nous voulions trouver le reste de la division de $7^{100}$ par $5$. Il serait fastidieux de multiplier sérieusement $7$ cent fois avant de diviser par $5$, mais en utilisant la propriété des congruences, puisque $7 \equiv 2 \pmod 5$, on a $7^{100} \equiv 2^{100} \pmod 5$, ce qui permet de simplifier considérablement le calcul. Dans le monde de la cryptographie, on manipule des puissances de très grands nombres, cette propriété est donc indispensable.&lt;/p>
&lt;hr>
&lt;h2 id="4-base-mathématique-de-la-cryptographie-rsa-3--la-fonction-deuler-et-le-théorème-deuler">4. Base mathématique de la cryptographie RSA 3 : La fonction d&amp;rsquo;Euler et le théorème d&amp;rsquo;Euler
&lt;/h2>&lt;p>Voici la mathématique magique qui est au cœur de la cryptographie RSA. Le « théorème d&amp;rsquo;Euler », qui est une généralisation du « petit théorème de Fermat », fait son apparition.&lt;/p>
&lt;h3 id="41-lindicatrice-deuler-phin">4.1 L&amp;rsquo;indicatrice d&amp;rsquo;Euler $\phi(N)$
&lt;/h3>&lt;p>La fonction indicatrice d&amp;rsquo;Euler (fonction $\phi$) est une fonction qui, pour un entier naturel $N$ donné, renvoie le &lt;strong>« nombre d&amp;rsquo;entiers naturels compris entre 1 et $N$ qui sont premiers avec $N$ (dont le plus grand commun diviseur est 1) »&lt;/strong>.&lt;/p>
&lt;p>Regardons quelques exemples.&lt;/p>
&lt;ul>
&lt;li>$\phi(5)$ : Parmi 1, 2, 3, 4, 5, les nombres premiers avec 5 sont 1, 2, 3, 4, soit 4 nombres. Donc, $\phi(5) = 4$.&lt;/li>
&lt;li>$\phi(6)$ : Parmi 1, 2, 3, 4, 5, 6, les nombres premiers avec 6 sont 1, 5, soit 2 nombres. Donc, $\phi(6) = 2$.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>【Propriété spéciale dans le cas d&amp;rsquo;un nombre premier】&lt;/strong>
Si $p$ est un nombre premier, tous les nombres de 1 à $p-1$ sont premiers avec $p$. Par conséquent,
&lt;/p>
$$ \phi(p) = p - 1 $$
&lt;p>&lt;strong>【Propriété spéciale dans le cas du produit de deux nombres premiers】&lt;/strong>
Pour deux nombres premiers distincts $p$ et $q$, si on pose $N = p \times q$, $\phi(N)$ peut être facilement calculée avec la formule suivante.
&lt;/p>
$$ \phi(N) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$
&lt;p>
Cette propriété agit comme la « porte dérobée secrète (trapdoor) » de la cryptographie RSA. La personne qui connaît $p$ et $q$ (le créateur de la clé) peut calculer $\phi(N)$ en un instant, mais une tierce personne qui ne connaît que $N$ ne peut pas trouver $\phi(N)$ sans factoriser $N$.&lt;/p>
&lt;h3 id="42-le-théorème-deuler">4.2 Le théorème d&amp;rsquo;Euler
&lt;/h3>&lt;p>Leonhard Euler a prouvé le magnifique théorème suivant en utilisant cette $\phi(N)$.&lt;/p>
&lt;p>&lt;strong>Théorème d&amp;rsquo;Euler :&lt;/strong>
Si les entiers $a$ et $N$ sont premiers entre eux, la congruence suivante est vraie :
&lt;/p>
$$ a^{\phi(N)} \equiv 1 \pmod N $$
&lt;p>C&amp;rsquo;est une propriété surprenante selon laquelle « si l&amp;rsquo;on multiplie un certain nombre $a$ par lui-même $\phi(N)$ fois et qu&amp;rsquo;on le divise par $N$, le reste sera toujours $1$ ». (Si $N$ est un nombre premier $p$, cela devient $a^{p-1} \equiv 1 \pmod p$, ce qui est appelé le petit théorème de Fermat).&lt;/p>
&lt;p>Transformons ce théorème d&amp;rsquo;Euler. Multiplions les deux côtés par $a$ une fois de plus.
&lt;/p>
$$ a^{\phi(N) + 1} \equiv a \pmod N $$
&lt;p>De plus, pour tout entier $k$, comme $a^{k \cdot \phi(N)}$ sera également égal à $1^k = 1$, l&amp;rsquo;équation suivante est vraie :
&lt;/p>
$$ a^{k \cdot \phi(N) + 1} \equiv a \pmod N $$
&lt;p>Cette équation est le principe fondamental qui permet à la magie de la cryptographie RSA de fonctionner : &lt;strong>« chiffrer puis déchiffrer permet de revenir à l&amp;rsquo;original »&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="5-algorithme-de-la-cryptographie-rsa--étapes-de-génération-de-clé-de-chiffrement-et-de-déchiffrement">5. Algorithme de la cryptographie RSA : Étapes de génération de clé, de chiffrement et de déchiffrement
&lt;/h2>&lt;p>Maintenant que nous avons les connaissances de base, examinons les étapes spécifiques de la cryptographie RSA. La cryptographie RSA est globalement divisée en trois phases : « 1. Génération de la clé », « 2. Chiffrement » et « 3. Déchiffrement ».&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Choisir les nombres premiers p, q"] --> A2["Calculer N = p × q"]
A1 --> A3["Calculer φ(N) = (p-1)(q-1)"]
A3 --> A4["Choisir e premier avec φ(N)"]
A3 --> A5["Calculer d tel que e × d ≡ 1 (mod φ(N))"]
A2 --> A6["Clé publique (N, e)"]
A4 --> A6
A5 --> A7["Clé privée d"]
B1["2. Message en texte clair M"] --> B2["Calculer C ≡ M^e (mod N)"]
A6 -.-> B2
B2 --> B3["Envoyer le texte chiffré C"]
B3 --> C1["3. Texte chiffré reçu C"]
C1 --> C2["Calculer M ≡ C^d (mod N)"]
A7 -.-> C2
C2 --> C3["Obtenir le message en texte clair d'origine M"]&lt;/div>
&lt;h3 id="51-génération-de-clé-key-generation">5.1 Génération de clé (Key Generation)
&lt;/h3>&lt;p>Bob, qui est le destinataire, génère sa « clé publique » et sa « clé privée ».&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Sélection des nombres premiers :&lt;/strong> Il choisit aléatoirement deux grands nombres premiers $p$ et $q$.&lt;/li>
&lt;li>&lt;strong>Calcul du module $N$ :&lt;/strong> Il calcule $N = p \times q$. Ce $N$ est rendu public.&lt;/li>
&lt;li>&lt;strong>Calcul de $\phi(N)$ :&lt;/strong> Il calcule la fonction d&amp;rsquo;Euler $\phi(N) = (p - 1)(q - 1)$. C&amp;rsquo;est le nombre secret de Bob uniquement.&lt;/li>
&lt;li>&lt;strong>Sélection de la clé publique $e$ :&lt;/strong> Il choisit un entier $e$ tel que $1 &lt; e &lt; \phi(N)$ et qui est premier avec $\phi(N)$.&lt;/li>
&lt;li>&lt;strong>Calcul de la clé privée $d$ :&lt;/strong> Il trouve un entier $d$ qui satisfait la condition suivante.
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
En d&amp;rsquo;autres termes, c&amp;rsquo;est « un nombre $d$ tel que le reste de $e \times d$ divisé par $\phi(N)$ est égal à $1$ ».&lt;/li>
&lt;/ol>
&lt;p>La préparation de la clé est maintenant terminée.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Clé publique :&lt;/strong> La paire $(N, e)$. Elle est publiée dans le monde entier.&lt;/li>
&lt;li>&lt;strong>Clé privée :&lt;/strong> $d$. Il ne le dit absolument à personne.&lt;/li>
&lt;/ul>
&lt;h3 id="52-chiffrement-encryption">5.2 Chiffrement (Encryption)
&lt;/h3>&lt;p>Supposons qu&amp;rsquo;Alice veuille envoyer un message secret $M$ à Bob. (On suppose que $M$ est un nombre représentant des caractères et $0 \le M &lt; N$). Alice utilise la clé publique de Bob $(N, e)$ et calcule comme suit :&lt;/p>
$$ C \equiv M^e \pmod N $$
&lt;p>Elle calcule « le reste $C$ de la division de la puissance $e$ du message $M$ par $N$ ». Ce $C$ est le texte chiffré.&lt;/p>
&lt;h3 id="53-déchiffrement-decryption">5.3 Déchiffrement (Decryption)
&lt;/h3>&lt;p>Bob reçoit le texte chiffré $C$. Bob utilise sa clé privée $d$ et calcule comme suit :&lt;/p>
$$ M \equiv C^d \pmod N $$
&lt;p>En calculant « le reste de la division de la puissance $d$ du texte chiffré $C$ par $N$ », étonnamment, le message d&amp;rsquo;origine $M$ est restauré !&lt;/p>
&lt;hr>
&lt;h2 id="6-pourquoi-le-déchiffrement-permet-il-de-revenir-à-loriginal--preuve-mathématique">6. Pourquoi le déchiffrement permet-il de revenir à l&amp;rsquo;original ? (Preuve mathématique)
&lt;/h2>&lt;p>Vous vous demandez peut-être : « Comment se fait-il que le simple fait d&amp;rsquo;élever $C$ à la puissance $d$ nous ramène au $M$ d&amp;rsquo;origine ? ». C&amp;rsquo;est ici que le « théorème d&amp;rsquo;Euler » que nous avons vu plus tôt entre en jeu.&lt;/p>
&lt;p>Substituons la formule de chiffrement $C = M^e$ dans la formule de déchiffrement $C^d \pmod N$.
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Rappelez-vous ici de l&amp;rsquo;étape 5 de la génération de clé. Lors de la création de $d$, Bob l&amp;rsquo;a choisi de sorte que $e \times d \equiv 1 \pmod{\phi(N)}$. Cela signifie que « $ed$ est un multiple de $\phi(N)$ plus $1$ ». En utilisant un entier $k$, on peut l&amp;rsquo;écrire comme suit :
&lt;/p>
$$ ed = k \cdot \phi(N) + 1 $$
&lt;p>Substituons cela dans l&amp;rsquo;exposant et décomposons-le en utilisant les lois des exposants.
&lt;/p>
$$ M^{ed} = M^{k \cdot \phi(N) + 1} = M^{k \cdot \phi(N)} \times M^1 = (M^{\phi(N)})^k \times M $$
&lt;p>Ici, en supposant que le message $M$ et $N$ sont premiers entre eux, d&amp;rsquo;après le &lt;strong>théorème d&amp;rsquo;Euler&lt;/strong>, on a $M^{\phi(N)} \equiv 1 \pmod N$.
&lt;/p>
$$ (M^{\phi(N)})^k \times M \equiv 1^k \times M \equiv M \pmod N $$
&lt;p>Par conséquent, la formule suivante est magnifiquement vérifiée.
&lt;/p>
$$ C^d \equiv M \pmod N $$
&lt;p>Alice ne connaît pas $d$, et les personnes sur écoute ne connaissent pas $d$ non plus, donc seul Bob, qui possède $d$, peut extraire $M$ de $C$.&lt;/p>
&lt;hr>
&lt;h2 id="7-exemple-concret--faisons-lexpérience-de-rsa-par-un-calcul-manuel-avec-de-petits-nombres-premiers">7. Exemple concret : Faisons l&amp;rsquo;expérience de RSA par un calcul manuel avec de petits nombres premiers
&lt;/h2>&lt;p>Faisons une communication chiffrée d&amp;rsquo;Alice à Bob en utilisant de petits nombres (nombres premiers) en pratique.&lt;/p>
&lt;p>&lt;strong>【Phase de génération de la clé de Bob】&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Choisir deux nombres premiers $p=11$, $q=13$.&lt;/li>
&lt;li>Calculer $N = 11 \times 13 = 143$.&lt;/li>
&lt;li>Calculer $\phi(N) = (11 - 1) \times (13 - 1) = 10 \times 12 = 120$.&lt;/li>
&lt;li>Choisir une clé publique $e$ première avec $\phi(N)=120$. Prenons ici $e=7$.&lt;/li>
&lt;li>Trouver la clé privée $d$. Chercher $d$ tel que $7 \times d \equiv 1 \pmod{120}$.
Dans l&amp;rsquo;équation $7d = 120k + 1$, pour $k=6$, on obtient $721$, et $721 \div 7 = 103$.
Donc, $d = 103$.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Clé publique : $(N=143, e=7)$&lt;/li>
&lt;li>Clé privée : $d=103$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>【Phase de chiffrement d&amp;rsquo;Alice】&lt;/strong>
Supposons que nous voulions envoyer le message $M = 9$.
Formule : $C \equiv 9^7 \pmod{143}$
$9^7 = 4,782,969$. Divisé par 143, cela donne $33447$ avec un reste de $48$.
Le texte chiffré est devenu $C = 48$.&lt;/p>
&lt;p>&lt;strong>【Phase de déchiffrement de Bob】&lt;/strong>
Bob reçoit le texte chiffré $C = 48$ et le déchiffre à l&amp;rsquo;aide de sa clé privée $d = 103$.
Formule : $M \equiv 48^{103} \pmod{143}$
Si vous exécutez &lt;code>(48 ** 103) % 143&lt;/code> sur une calculatrice, le résultat est magnifiquement « &lt;strong>9&lt;/strong> » ! Il a pu recevoir avec succès le message d&amp;rsquo;origine.&lt;/p>
&lt;hr>
&lt;h2 id="8-comment-trouver-la-clé-privée-d--lalgorithme-deuclide-étendu">8. Comment trouver la clé privée $d$ : L&amp;rsquo;algorithme d&amp;rsquo;Euclide étendu
&lt;/h2>&lt;p>Dans l&amp;rsquo;exemple de calcul manuel, nous avons trouvé $k$ par intuition pour découvrir $d=103$, mais cette méthode est impossible lorsque les nombres atteignent des centaines de chiffres. Dans les programmes réels, nous utilisons un algorithme appelé &lt;strong>« algorithme d&amp;rsquo;Euclide étendu »&lt;/strong>.&lt;/p>
&lt;p>Résoudre $7d \equiv 1 \pmod{120}$ équivaut à trouver des entiers $d, y$ qui satisfont $7d + 120y = 1$. En calculant à l&amp;rsquo;envers avec l&amp;rsquo;algorithme d&amp;rsquo;Euclide, nous pouvons le trouver mécaniquement.&lt;/p>
&lt;ol>
&lt;li>$120 \div 7 = 17$ reste $1$&lt;/li>
&lt;li>En transformant cela, $1 = 120 - 17 \times 7$&lt;/li>
&lt;li>En d&amp;rsquo;autres termes, $-17 \times 7 \equiv 1 \pmod{120}$&lt;/li>
&lt;/ol>
&lt;p>$-17$ signifie la même chose que $120 - 17 = 103$ dans le monde du modulo $120$. Par conséquent, on trouve $d = 103$ en un instant. Cette méthode permet de calculer très rapidement même pour des nombres extrêmement grands.&lt;/p>
&lt;hr>
&lt;h2 id="9-lautre-visage-de-la-cryptographie-rsa--les-signatures-numériques">9. L&amp;rsquo;autre visage de la cryptographie RSA : Les signatures numériques
&lt;/h2>&lt;p>Ce qui est merveilleux avec la cryptographie RSA, c&amp;rsquo;est qu&amp;rsquo;en inversant les rôles de la clé publique et de la clé privée, on peut aussi l&amp;rsquo;utiliser comme &lt;strong>« signature numérique »&lt;/strong>.&lt;/p>
&lt;p>Pour le chiffrement, c&amp;rsquo;était « chiffrement avec la clé publique $\Rightarrow$ déchiffrement avec la clé privée », mais
pour la signature numérique, on suit les étapes : « chiffrement avec la clé privée $\Rightarrow$ déchiffrement avec la clé publique ».&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Alice crée une signature avec sa clé privée"] --> A2["S ≡ M^d (mod N)"]
A2 --> A3["Envoyer le message M et la signature S"]
A3 --> B1["2. Bob vérifie la signature avec la clé publique"]
B1 --> B2["Calculer M' ≡ S^e (mod N)"]
B2 --> B3["Vérifier si M' et M correspondent"]&lt;/div>
&lt;p>Alice convertit le message en utilisant sa propre clé privée $d$ (c&amp;rsquo;est la signature $S$) et l&amp;rsquo;envoie à Bob. Bob effectue le calcul de vérification en utilisant la clé publique $e$ d&amp;rsquo;Alice. Si le résultat du calcul correspond au message d&amp;rsquo;origine, cela prouve simultanément que « ce sont des données qui ne peuvent être créées qu&amp;rsquo;avec la clé privée d&amp;rsquo;Alice » et que « le message n&amp;rsquo;a pas été falsifié en cours de route ».&lt;/p>
&lt;hr>
&lt;h2 id="10-expérimenter-la-cryptographie-rsa-avec-la-programmation">10. Expérimenter la cryptographie RSA avec la programmation
&lt;/h2>&lt;p>Même les calculs de puissance qui sont difficiles à faire à la main peuvent être très facilement implémentés avec Python. Voici un code Python qui vous permet d&amp;rsquo;expérimenter la logique de base de la cryptographie RSA.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Trouver le plus grand commun diviseur&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Trouver la clé privée d (utilisation de la fonction intégrée à partir de Python 3.8)&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Génération de clé&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">13&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">N&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Clé publique : (N=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, e=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">), Clé privée : d=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Chiffrement&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">9&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Texte chiffré : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Déchiffrement&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">decrypted_message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Message déchiffré : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted_message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>La fonction &lt;code>pow(base, exp, mod)&lt;/code> de Python utilise un algorithme rapide appelé « exponentiation rapide (par carrés successifs) » en interne, de sorte que même pour des nombres de centaines de chiffres, le calcul se termine en un clin d&amp;rsquo;œil.&lt;/p>
&lt;hr>
&lt;h2 id="11-résumé-et-avenir-des-technologies-cryptographiques">11. Résumé et avenir des technologies cryptographiques
&lt;/h2>&lt;p>Nous avons percé les secrets du mécanisme de la cryptographie RSA, en nous basant sur les connaissances mathématiques du lycée.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>La difficulté de la décomposition en facteurs premiers :&lt;/strong> Il est facile de calculer $p \times q = N$, mais il est très difficile de trouver $p, q$ à partir de $N$.&lt;/li>
&lt;li>&lt;strong>Congruence et théorème d&amp;rsquo;Euler :&lt;/strong> Grâce à la règle $a^{\phi(N)} \equiv 1 \pmod N$, la porte dérobée magique « revenir à l&amp;rsquo;original lorsqu&amp;rsquo;on élève à une certaine puissance » est achevée.&lt;/li>
&lt;li>&lt;strong>Clé publique et clé privée :&lt;/strong> N&amp;rsquo;importe qui peut chiffrer, mais seul le destinataire légitime peut déchiffrer.&lt;/li>
&lt;/ol>
&lt;p>Le $N$ de la cryptographie RSA actuellement utilisé comporte plus de 600 chiffres, et même si on mobilisait tous les superordinateurs du monde, la décomposition en facteurs premiers prendrait plus de temps que l&amp;rsquo;âge de l&amp;rsquo;univers. Cependant, si les « ordinateurs quantiques » dont la recherche a progressé ces dernières années deviennent un jour utilisables en pratique, cette décomposition pourrait être résolue en un instant grâce à l&amp;rsquo;« algorithme de Shor ». Pour cette raison, le développement d&amp;rsquo;une « cryptographie post-quantique », qui ne pourrait pas être cassée même par des ordinateurs quantiques, avance rapidement partout dans le monde.&lt;/p>
&lt;p>Les mathématiques avancées, souvent perçues comme « inutiles », protègent en réalité fondamentalement notre vie quotidienne. La cryptographie RSA est le meilleur matériel pédagogique qui nous enseigne la profondeur et la beauté de telles mathématiques. J&amp;rsquo;espère qu&amp;rsquo;à travers cet article, vous avez pu ressentir, ne serait-ce qu&amp;rsquo;un peu, l&amp;rsquo;intérêt de la cryptographie et des mathématiques.&lt;/p></description></item><item><title>Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++</title><link>http://kenji.blog/fr/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/elliptic-curve-cryptography-math-cpp/</guid><description>&lt;img src="http://kenji.blog/p/elliptic-curve-cryptography-math-cpp/img/eyecatch.jpg" alt="Featured image of post Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++" />&lt;h1 id="fondements-mathématiques-de-la-cryptographie-sur-les-courbes-elliptiques-ecc-et-implémentation-en-c">Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++
&lt;/h1>&lt;p>Dans les technologies de cryptographie modernes, la &lt;strong>cryptographie sur les courbes elliptiques (Elliptic Curve Cryptography : ECC)&lt;/strong> joue un rôle extrêmement important. De nos communications Internet quotidiennes (HTTPS/TLS) aux enclaves sécurisées des smartphones, en passant par l&amp;rsquo;authentification des serveurs via SSH, l&amp;rsquo;authentification sans mot de passe comme FIDO, et même les crypto-actifs tels que Bitcoin et Ethereum, on peut dire sans exagérer que la base de confiance de la société numérique moderne est soutenue par l&amp;rsquo;ECC.&lt;/p>
&lt;p>Dans cet article, nous expliquerons en profondeur, avec un volume de contenu impressionnant, le fonctionnement de cette cryptographie sur les courbes elliptiques. Nous partirons de la théorie mathématique sous-jacente, belle mais complexe (géométrie algébrique sur les corps finis), pour aller jusqu&amp;rsquo;à la méthode d&amp;rsquo;implémentation réelle en C++, et enfin aux techniques de codage sécurisé pour prévenir les attaques par canaux auxiliaires (attaques temporelles).&lt;/p>
&lt;hr>
&lt;h2 id="1-pourquoi-la-cryptographie-sur-les-courbes-elliptiques--comparaison-avec-rsa">1. Pourquoi la cryptographie sur les courbes elliptiques ? (Comparaison avec RSA)
&lt;/h2>&lt;p>Pendant longtemps, le synonyme de cryptographie à clé publique a été la &lt;strong>cryptographie RSA&lt;/strong>. La sécurité de RSA repose sur la &amp;ldquo;difficulté de la factorisation en nombres premiers de très grands nombres composés&amp;rdquo;. Cependant, avec l&amp;rsquo;amélioration de la puissance de calcul des ordinateurs, il a été nécessaire d&amp;rsquo;allonger continuellement la taille des clés RSA (le nombre de bits du module) pour maintenir la sécurité. Aujourd&amp;rsquo;hui, une taille de clé d&amp;rsquo;au moins 2048 bits est recommandée, voire 3072 bits ou 4096 bits pour plus de sécurité.&lt;/p>
&lt;p>En revanche, la cryptographie sur les courbes elliptiques (ECC) repose sur une autre difficulté mathématique appelée le &lt;strong>&amp;ldquo;problème du logarithme discret sur les courbes elliptiques (ECDLP)&amp;rdquo;&lt;/strong>. Jusqu&amp;rsquo;à présent, aucun algorithme efficace (comme les algorithmes en temps sous-exponentiel) pour résoudre l&amp;rsquo;ECDLP n&amp;rsquo;a été découvert, et même les méthodes d&amp;rsquo;attaque les plus efficaces connues nécessitent un temps exponentiel.&lt;/p>
&lt;p>Grâce à cette propriété, l&amp;rsquo;ECC possède l&amp;rsquo;avantage décisif de &lt;strong>pouvoir atteindre un niveau de sécurité équivalent à celui de RSA avec une taille de clé beaucoup plus courte&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">Niveau de sécurité (bits)&lt;/th>
&lt;th style="text-align:center">Taille de clé RSA (bits)&lt;/th>
&lt;th style="text-align:center">Taille de clé ECC (bits)&lt;/th>
&lt;th style="text-align:center">Ratio des tailles de clé&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">80&lt;/td>
&lt;td style="text-align:center">1024&lt;/td>
&lt;td style="text-align:center">160&lt;/td>
&lt;td style="text-align:center">1:6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">112&lt;/td>
&lt;td style="text-align:center">2048&lt;/td>
&lt;td style="text-align:center">224&lt;/td>
&lt;td style="text-align:center">1:9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">128&lt;/td>
&lt;td style="text-align:center">3072&lt;/td>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">1:12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">192&lt;/td>
&lt;td style="text-align:center">7680&lt;/td>
&lt;td style="text-align:center">384&lt;/td>
&lt;td style="text-align:center">1:20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">15360&lt;/td>
&lt;td style="text-align:center">512&lt;/td>
&lt;td style="text-align:center">1:30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Comme le montre le tableau ci-dessus, pour obtenir un niveau de sécurité de 128 bits (le standard actuel), RSA nécessite une clé de 3072 bits, alors que l&amp;rsquo;ECC ne nécessite que 256 bits. Cela permet de réduire la quantité de calculs, l&amp;rsquo;utilisation de la mémoire et d&amp;rsquo;économiser la bande passante du réseau. L&amp;rsquo;ECC présente ainsi une supériorité écrasante, en particulier dans les environnements aux ressources limitées comme les appareils IoT et les cartes à puce.&lt;/p>
&lt;hr>
&lt;h2 id="2-prérequis-mathématiques--la-théorie-des-groupes-et-le-monde-des-corps-finis">2. Prérequis mathématiques : La théorie des groupes et le monde des corps finis
&lt;/h2>&lt;p>Pour véritablement comprendre la cryptographie sur les courbes elliptiques, il est nécessaire de maîtriser les concepts de base de l&amp;rsquo;algèbre abstraite (théorie des groupes et théorie des corps). Nous résumons ici brièvement les connaissances préalables pour construire l&amp;rsquo;ECC.&lt;/p>
&lt;h3 id="21-groupes-group-et-groupes-abéliens">2.1. Groupes (Group) et Groupes abéliens
&lt;/h3>&lt;p>Un &lt;strong>groupe (Group)&lt;/strong> est défini par un ensemble $G$ et une opération binaire sur cet ensemble (nous utiliserons ici l&amp;rsquo;addition $+$) formant une paire $(G, +)$ qui satisfait aux 4 axiomes suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Clôture (Closure)&lt;/strong> : Pour tous $a, b \in G$, $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>Associativité (Associativity)&lt;/strong> : Pour tous $a, b, c \in G$, $(a + b) + c = a + (b + c)$.&lt;/li>
&lt;li>&lt;strong>Existence de l&amp;rsquo;élément neutre (Identity element)&lt;/strong> : Il existe un élément $e \in G$ tel que pour tout $a \in G$, $a + e = e + a = a$. Dans le cas d&amp;rsquo;un groupe additif, cet élément neutre est généralement noté $0$ ou $\mathcal{O}$.&lt;/li>
&lt;li>&lt;strong>Existence de l&amp;rsquo;inverse (Inverse element)&lt;/strong> : Pour tout $a \in G$, il existe un élément $b \in G$ tel que $a + b = b + a = e$. Ce $b$ est noté $-a$.&lt;/li>
&lt;/ol>
&lt;p>De plus, un groupe qui satisfait la condition suivante, où l&amp;rsquo;ordre des opérations ne change pas le résultat, est appelé un &lt;strong>groupe abélien (ou groupe commutatif)&lt;/strong> :&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>Commutativité (Commutativity)&lt;/strong> : Pour tous $a, b \in G$, $a + b = b + a$.&lt;/li>
&lt;/ol>
&lt;p>L&amp;rsquo;ensemble des points sur une courbe elliptique forme ce &lt;strong>groupe abélien&lt;/strong> en définissant une règle d&amp;rsquo;addition spécifique.&lt;/p>
&lt;h3 id="22-corps-finis-finite-field">2.2. Corps finis (Finite Field)
&lt;/h3>&lt;p>Dans la théorie cryptographique, nous n&amp;rsquo;utilisons pas des corps ayant un nombre infini et continu d&amp;rsquo;éléments comme les nombres réels ou complexes, mais plutôt des &lt;strong>corps finis (Finite Field)&lt;/strong> ou corps de Galois (Galois Field), dont le nombre d&amp;rsquo;éléments est fini.&lt;/p>
&lt;p>Le corps fini le plus fondamental est le &lt;strong>corps premier $\mathbb{F}_p$&lt;/strong> utilisant un nombre premier $p$. Il s&amp;rsquo;agit de l&amp;rsquo;ensemble des entiers $\{0, 1, 2, \dots, p-1\}$ muni des quatre opérations arithmétiques (addition, soustraction, multiplication, division) définies modulo $p$ (le reste de la division par $p$).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Addition&lt;/strong> : $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Soustraction&lt;/strong> : $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Multiplication&lt;/strong> : $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Division&lt;/strong> : $a \times b^{-1} \pmod p$ (où $b^{-1}$ est l&amp;rsquo;inverse multiplicatif de $b$ modulo $p$)&lt;/li>
&lt;/ul>
&lt;p>Le calcul de l&amp;rsquo;&lt;strong>inverse multiplicatif (Modular Multiplicative Inverse)&lt;/strong> est extrêmement important dans l&amp;rsquo;implémentation cryptographique. Pour trouver $b^{-1}$ satisfaisant $b \times b^{-1} \equiv 1 \pmod p$, les deux algorithmes suivants sont principalement utilisés :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Algorithme d&amp;rsquo;Euclide étendu (Extended Euclidean Algorithm)&lt;/strong> : Il est rapide, mais selon l&amp;rsquo;implémentation, le temps de traitement dépend des valeurs d&amp;rsquo;entrée, ce qui présente un risque d&amp;rsquo;attaque temporelle.&lt;/li>
&lt;li>&lt;strong>Petit théorème de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong> : Lorsque $p$ est un nombre premier et $b \neq 0$, $b^{p-1} \equiv 1 \pmod p$ est vrai. En divisant les deux côtés par $b$, on obtient $b^{p-2} \equiv b^{-1} \pmod p$. Autrement dit, l&amp;rsquo;inverse peut être trouvé en calculant $b$ à la puissance $p-2$. Comme l&amp;rsquo;opération d&amp;rsquo;exponentiation est plus facile à implémenter en temps constant, elle est préférée dans les implémentations cryptographiques.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-léquation-de-la-courbe-elliptique-et-géométrie">3. L&amp;rsquo;équation de la courbe elliptique et géométrie
&lt;/h2>&lt;h3 id="31-forme-normale-de-weierstrass">3.1. Forme normale de Weierstrass
&lt;/h3>&lt;p>Une &lt;strong>courbe elliptique (Elliptic Curve)&lt;/strong> est une courbe plane généralement définie par l&amp;rsquo;équation suivante, appelée &lt;strong>forme normale de Weierstrass (Weierstrass normal form)&lt;/strong> :&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>Ici, $a$ et $b$ sont des constantes, et pour que la courbe n&amp;rsquo;ait pas de points singuliers (auto-intersections ou points de rebroussement) (pour qu&amp;rsquo;elle soit une courbe lisse), la condition est que le &lt;strong>discriminant (Discriminant) $\Delta$&lt;/strong> suivant ne soit pas nul :&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>Les courbes avec des points singuliers compromettent la sécurité cryptographique, c&amp;rsquo;est pourquoi on choisit toujours des coefficients $a, b$ qui satisfont à cette condition.&lt;/p>
&lt;h3 id="32-le-point-à-linfini-point-at-infinity">3.2. Le point à l&amp;rsquo;infini (Point at Infinity)
&lt;/h3>&lt;p>Pour faire de la courbe elliptique un groupe mathématiquement complet, en plus des points sur le plan, un point virtuel appelé &lt;strong>&amp;ldquo;point à l&amp;rsquo;infini (Point at Infinity)&amp;rdquo;&lt;/strong> est introduit. Il est noté $\mathcal{O}$ (O majuscule).&lt;/p>
&lt;p>Le point à l&amp;rsquo;infini $\mathcal{O}$ est défini comme le point où toutes les lignes verticales se croisent à l&amp;rsquo;infini. Dans la théorie des groupes, ce point à l&amp;rsquo;infini $\mathcal{O}$ fonctionne comme &lt;strong>l&amp;rsquo;élément neutre de l&amp;rsquo;addition&lt;/strong> (zéro).&lt;/p>
&lt;p>Autrement dit, pour tout point $P$ sur la courbe :
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>De plus, l&amp;rsquo;inverse $-P$ du point $P = (x, y)$ est défini comme le point symétrique par rapport à l&amp;rsquo;axe des x, soit $(x, -y)$. Par conséquent :
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;hr>
&lt;h2 id="4-opérations-de-groupe-sur-la-courbe-elliptique-addition-de-points-et-doublement">4. Opérations de groupe sur la courbe elliptique (Addition de points et doublement)
&lt;/h2>&lt;p>Le fondement de la cryptographie sur les courbes elliptiques est l&amp;rsquo;opération d&amp;rsquo;&lt;strong>&amp;ldquo;addition (Addition)&amp;rdquo;&lt;/strong> de points sur la courbe. Ceci est différent de l&amp;rsquo;addition d&amp;rsquo;entiers ordinaires et est défini sur la base d&amp;rsquo;opérations géométriques.&lt;/p>
&lt;h3 id="41-addition-géométrique-méthode-de-la-tangente-et-de-la-sécante">4.1. Addition géométrique (Méthode de la tangente et de la sécante)
&lt;/h3>&lt;p>La procédure pour ajouter deux points distincts $P$ et $Q$ sur la courbe pour obtenir un nouveau point $R$ ($R = P + Q$) est la suivante :&lt;/p>
&lt;ol>
&lt;li>Tracez une ligne droite (sécante) passant par les points $P$ et $Q$.&lt;/li>
&lt;li>Cette droite coupera toujours la courbe elliptique en un autre point (que nous appellerons $-R$). (*Selon un théorème de la géométrie algébrique)&lt;/li>
&lt;li>Le point symétrique de l&amp;rsquo;intersection $-R$ par rapport à l&amp;rsquo;axe des x (le point avec le signe de la coordonnée y inversé) est le point recherché $R$.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["Tracer une droite reliant P(x1, y1) et Q(x2, y2)"] --> Step2["Trouver la 3ème intersection avec la courbe, -R"]
Step2 --> Step3["Refléter -R sur l'axe des x pour obtenir R(x3, y3)"]
Step3 -.-> Result["Ceci est R = P + Q"]&lt;/div>
&lt;h3 id="42-doublement-de-point-point-doubling">4.2. Doublement de point (Point Doubling)
&lt;/h3>&lt;p>Lorsque l&amp;rsquo;on ajoute le même point $P$ à $P$ ($P + P = 2P$), on ne peut pas tracer une ligne passant par deux points. Dans ce cas, nous tracons &lt;strong>la tangente (Tangent) à la courbe au point $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Tracez la tangente à la courbe au point $P$.&lt;/li>
&lt;li>Cette tangente coupera la courbe en un autre point $-R$.&lt;/li>
&lt;li>Le point symétrique de cette intersection par rapport à l&amp;rsquo;axe des x est le point recherché $R = 2P$.&lt;/li>
&lt;/ol>
&lt;h3 id="43-formules-de-calcul-algébrique">4.3. Formules de calcul algébrique
&lt;/h3>&lt;p>Nous transposons les opérations géométriques en formules algébriques afin qu&amp;rsquo;elles puissent être calculées par un ordinateur.
Tous les calculs sont effectués &lt;strong>sur le corps fini $\mathbb{F}_p$ (modulo $p$)&lt;/strong>.&lt;/p>
&lt;p>Soient le point $P = (x_1, y_1)$ et le point $Q = (x_2, y_2)$.
Et soit le point de résultat calculé $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>Soit $\lambda$ (lambda) la pente de la droite.&lt;/p>
&lt;p>&lt;strong>[Cas 1 : Lorsque $P \neq Q$ (Addition de points)]&lt;/strong>
La pente $\lambda$ est le taux de variation entre les deux points.
&lt;/p>
$$ \lambda \equiv \frac{y_2 - y_1}{x_2 - x_1} \pmod p $$
$$ \lambda \equiv (y_2 - y_1) \cdot (x_2 - x_1)^{-1} \pmod p $$
&lt;p>En utilisant ce $\lambda$, $x_3, y_3$ sont calculés comme suit :
&lt;/p>
$$ x_3 \equiv \lambda^2 - x_1 - x_2 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;p>&lt;strong>[Cas 2 : Lorsque $P = Q$ (Doublement de point)]&lt;/strong>
La pente $\lambda$ est la pente de la tangente obtenue par dérivation. (On dérive implicitement $y^2 = x^3 + ax + b$)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
Par conséquent,
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>Les équations pour $x_3, y_3$ ont la même forme que l&amp;rsquo;addition, mais puisque $x_2 = x_1$, elles deviennent :
&lt;/p>
$$ x_3 \equiv \lambda^2 - 2x_1 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;blockquote>
&lt;p>[!IMPORTANT]
Ces formules contiennent des &lt;strong>divisions (calcul de l&amp;rsquo;inverse modulo)&lt;/strong> telles que $(x_2 - x_1)^{-1}$ et $(2y_1)^{-1}$. Le calcul de l&amp;rsquo;inverse modulo ayant un coût de calcul très élevé, les implémentations réelles utilisent généralement des systèmes de coordonnées projectives comme les &lt;strong>&amp;ldquo;coordonnées jacobiennes (Jacobian Coordinates)&amp;rdquo;&lt;/strong> pour retarder la division.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-multiplication-scalaire-et-problème-du-logarithme-discret-sur-les-courbes-elliptiques-ecdlp">5. Multiplication scalaire et problème du logarithme discret sur les courbes elliptiques (ECDLP)
&lt;/h2>&lt;p>Dans la cryptographie sur les courbes elliptiques, l&amp;rsquo;opération qui demande le plus de calculs et qui constitue le cœur de la sécurité est la &lt;strong>multiplication scalaire (Scalar Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="51-quest-ce-que-la-multiplication-scalaire-">5.1. Qu&amp;rsquo;est-ce que la multiplication scalaire ?
&lt;/h3>&lt;p>L&amp;rsquo;opération consistant à additionner un certain point $P$, $k$ fois est appelée multiplication scalaire, notée $kP$.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k\text{ fois}} $$
&lt;p>Ici, $k$ est un très grand nombre entier (par exemple, un entier de 256 bits).&lt;/p>
&lt;h3 id="52-problème-du-logarithme-discret-sur-les-courbes-elliptiques-ecdlp">5.2. Problème du logarithme discret sur les courbes elliptiques (ECDLP)
&lt;/h3>&lt;p>La sécurité de l&amp;rsquo;ECC dépend de la difficulté du problème suivant :&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Problème du logarithme discret sur les courbes elliptiques (Elliptic Curve Discrete Logarithm Problem : ECDLP)&lt;/strong>
Étant donné un point connu $P$ (point de base) et un point calculé $Q$, trouver le scalaire $k$ tel que $Q = kP$.&lt;/p>
&lt;/blockquote>
&lt;p>Il est facile (en temps polynomial) de calculer $Q$ à partir de $k$ et $P$ (sens direct) en utilisant l&amp;rsquo;algorithme décrit plus loin, mais il est pratiquement impossible de calculer à l&amp;rsquo;envers $k$ à partir de $P$ et $Q$ (sens inverse), car il n&amp;rsquo;existe pas de méthode efficace autre que la recherche exhaustive (fonction à sens unique).
Dans les protocoles cryptographiques, &lt;strong>$k$ correspond à la &amp;ldquo;clé privée&amp;rdquo; et $Q$ à la &amp;ldquo;clé publique&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-lalgorithme-double-and-add">5.3. L&amp;rsquo;algorithme Double-and-Add
&lt;/h3>&lt;p>Lorsque $k$ est un nombre énorme (par exemple, $2^{256}$), l&amp;rsquo;addition naïve de $P$ $k$ fois ne se terminerait pas avant la fin de l&amp;rsquo;univers. Par conséquent, pour effectuer rapidement la multiplication scalaire, on utilise la méthode &lt;strong>Double-and-Add (méthode binaire)&lt;/strong>.&lt;/p>
&lt;p>C&amp;rsquo;est la version courbe elliptique de l&amp;rsquo;&amp;ldquo;exponentiation rapide&amp;rdquo; utilisée pour calculer rapidement les puissances entières. Le scalaire $k$ est représenté en binaire, et traité dans l&amp;rsquo;ordre, du bit de poids fort au bit de poids faible.&lt;/p>
&lt;ol>
&lt;li>Initialiser le point de résultat $R$ avec $\mathcal{O}$.&lt;/li>
&lt;li>Répéter ce qui suit du bit de poids fort de $k$ jusqu&amp;rsquo;au bit de poids faible :
&lt;ul>
&lt;li>Doubler $R$ (Point Doubling : $R = 2R$)&lt;/li>
&lt;li>Si le bit actuel est &lt;code>1&lt;/code>, ajouter $P$ à $R$ (Point Addition : $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Grâce à cet algorithme, la complexité passe de $O(k)$ à $O(\log_2 k)$ de façon drastique, permettant des calculs dans un temps réaliste (de l&amp;rsquo;ordre de la milliseconde).&lt;/p>
&lt;hr>
&lt;h2 id="6-léchange-de-clés-diffie-hellman-sur-courbes-elliptiques-ecdh">6. L&amp;rsquo;échange de clés Diffie-Hellman sur courbes elliptiques (ECDH)
&lt;/h2>&lt;p>Nous expliquons ici le fonctionnement du &lt;strong>protocole d&amp;rsquo;échange de clés ECDH (Elliptic Curve Diffie-Hellman)&lt;/strong>, qui est l&amp;rsquo;application la plus représentative de l&amp;rsquo;ECC. L&amp;rsquo;ECDH est un mécanisme permettant à Alice et Bob de générer et de partager en toute sécurité une clé secrète commune (clé de session) sur un canal de communication vulnérable à l&amp;rsquo;écoute (c&amp;rsquo;est le cœur du handshake TLS).&lt;/p>
&lt;p>&lt;strong>[Paramètres préalables (Paramètres de domaine)]&lt;/strong>
Les deux parties partagent au préalable la courbe elliptique $E$ à utiliser, le nombre premier $p$ et le point de base $G$. (Par exemple NIST P-256 ou secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "Alice"
participant Bob as "Bob"
Note over Alice,Bob: "Paramètres publics : Courbe E, point de base G, premier p"
Alice->>Alice: "Générer la clé privée d_A (entier aléatoire)"
Alice->>Alice: "Calculer la clé publique Q_A = d_A * G"
Bob->>Bob: "Générer la clé privée d_B (entier aléatoire)"
Bob->>Bob: "Calculer la clé publique Q_B = d_B * G"
Alice->>Bob: "Envoyer la clé publique Q_A (en clair)"
Bob->>Alice: "Envoyer la clé publique Q_B (en clair)"
Alice->>Alice: "Calculer le secret partagé S = d_A * Q_B"
Bob->>Bob: "Calculer le secret partagé S = d_B * Q_A"
Note over Alice,Bob: "S = d_A * (d_B * G) = d_B * (d_A * G) = (d_A * d_B) * G"
Note over Alice,Bob: "Les résultats de calcul S des deux parties correspondent parfaitement !"&lt;/div>
&lt;p>Un attaquant (Eve) peut intercepter $G$, $Q_A$ et $Q_B$ circulant sur le canal de communication, mais en raison de la difficulté de l&amp;rsquo;ECDLP, il ne peut pas déduire la clé privée d&amp;rsquo;Alice $d_A$ à partir de $Q_A = d_A \cdot G$. De plus, multiplier $Q_A$ et $Q_B$ ne donne pas la clé partagée $S$, donc un attaquant ne peut pas calculer $S$.&lt;/p>
&lt;hr>
&lt;h2 id="7-pièges-dimplémentation--attaques-par-canaux-auxiliaires-et-contre-mesures">7. Pièges d&amp;rsquo;implémentation : Attaques par canaux auxiliaires et contre-mesures
&lt;/h2>&lt;p>Même avec un algorithme cryptographique théoriquement parfait, des vulnérabilités peuvent apparaître lors du processus d&amp;rsquo;implémentation du programme. C&amp;rsquo;est ce qu&amp;rsquo;on appelle les &lt;strong>&amp;ldquo;attaques par canaux auxiliaires (Side-Channel Attack)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="71-attaque-temporelle-timing-attack">7.1. Attaque temporelle (Timing Attack)
&lt;/h3>&lt;p>Revenons sur l&amp;rsquo;algorithme Double-and-Add mentionné précédemment.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Pseudo-code vulnérable du Double-and-Add
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Infinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">255&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointDoubling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Toujours exécuté
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointAddition&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Exécuté uniquement quand le bit est à 1 !
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Cette implémentation présente un défaut fatal. Comme la Point Addition est exécutée lorsque le bit est &lt;code>1&lt;/code>, le temps de calcul est &lt;strong>légèrement plus long&lt;/strong> que lorsque le bit est &lt;code>0&lt;/code>. De plus, la prédiction de branchement du processeur et le comportement de la mémoire cache changent.
En observant statistiquement cette infime différence de temps de calcul (ou de consommation d&amp;rsquo;énergie) des milliers de fois, un attaquant peut &lt;strong>récupérer complètement la séquence de bits de la clé privée $k$ un par un&lt;/strong>. C&amp;rsquo;est une attaque temporelle.&lt;/p>
&lt;h3 id="72-implémentation-en-temps-constant-constant-time--léchelle-de-montgomery-montgomery-ladder">7.2. Implémentation en temps constant (Constant-Time) : L&amp;rsquo;échelle de Montgomery (Montgomery Ladder)
&lt;/h3>&lt;p>Pour empêcher les attaques temporelles, il est nécessaire d&amp;rsquo;adopter un algorithme dont &lt;strong>la séquence d&amp;rsquo;instructions exécutées et le temps de calcul sont toujours constants (Constant-Time), quelle que soit la valeur des bits de la clé privée&lt;/strong>.&lt;/p>
&lt;p>L&amp;rsquo;exemple le plus représentatif est l&amp;rsquo;&lt;strong>échelle de Montgomery (Montgomery Ladder)&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["Initialisation : R0 = O, R1 = P"] --> LoopStart["Pour chaque bit i (depuis le poids fort)"]
LoopStart --> Cond{"Valeur de k_i ?"}
Cond -->|0| Branch0["R1 = R0 + R1&lt;br>R0 = 2 * R0"]
Cond -->|1| Branch1["R0 = R0 + R1&lt;br>R1 = 2 * R1"]
Branch0 --> LoopEnd["Bit suivant"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"Tous les bits terminés"| End["Fin : R0 est le résultat (kP)"]&lt;/div>
&lt;p>La beauté de l&amp;rsquo;échelle de Montgomery réside dans le fait que, que le bit soit &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, &lt;strong>&amp;ldquo;exactement 1 Point Addition et 1 Point Doubling&amp;rdquo;&lt;/strong> sont toujours exécutés. Cela élimine complètement la dépendance des données sur le temps de calcul.&lt;/p>
&lt;p>Cependant, si le branchement conditionnel (&lt;code>if (k_i == 0)&lt;/code>) lui-même existe, il reste un risque que le temps d&amp;rsquo;exécution fluctue en raison des optimisations du compilateur ou de la prédiction de branchement du processeur. Par conséquent, dans les implémentations réelles en temps constant, les branchements conditionnels (instructions &lt;code>if&lt;/code>) sont éliminés, et un &lt;strong>échange conditionnel utilisant des opérations bit à bit (Conditional Swap)&lt;/strong> est utilisé.&lt;/p>
&lt;hr>
&lt;h2 id="8-implémentation-de-la-cryptographie-sur-les-courbes-elliptiques-en-c">8. Implémentation de la cryptographie sur les courbes elliptiques en C++
&lt;/h2>&lt;p>À partir de là, nous allons traduire la théorie en code C++. Les bibliothèques cryptographiques pratiques (telles que OpenSSL ou libsodium) utilisent des optimisations avancées en assembleur et des systèmes de coordonnées jacobiennes, mais ici, pour approfondir la compréhension mathématique, nous présenterons le squelette d&amp;rsquo;une &lt;strong>implémentation claire en temps constant utilisant des coordonnées affines&lt;/strong>.&lt;/p>
&lt;p>Nous supposerons l&amp;rsquo;utilisation de &lt;code>boost::multiprecision::cpp_int&lt;/code> pour les opérations sur les très grands entiers.&lt;/p>
&lt;h3 id="81-arithmétique-modulaire-et-inverse">8.1. Arithmétique modulaire et inverse
&lt;/h3>&lt;p>Tout d&amp;rsquo;abord, nous définissons des fonctions d&amp;rsquo;aide pour les opérations sur les corps finis. Nous implémentons le calcul de l&amp;rsquo;inverse en utilisant le petit théorème de Fermat.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;boost/multiprecision/cpp_int.hpp&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Exemple avec le premier p et les paramètres de secp256k1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Opération modulo retournant un reste positif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nl">m&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Calcul de l&amp;#39;exponentiation modulaire (x^y mod m)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">exp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">res&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Inverse modulo utilisant le petit théorème de Fermat
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Prémisse que m est premier : n^(m-2) ≡ n^(-1) mod m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="82-représentation-des-points-et-opérations-de-groupe-addition-doublement">8.2. Représentation des points et opérations de groupe (Addition, Doublement)
&lt;/h3>&lt;p>Nous définissons une structure &lt;code>Point&lt;/code> qui gère le point à l&amp;rsquo;infini avec un drapeau, et nous implémentons les formules d&amp;rsquo;addition.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Point&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">bool&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Création d&amp;#39;un point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Création d&amp;#39;un point normal
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Addition de points sur la courbe elliptique (R = P + Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// P + (-P) = Point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">lambda&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Point Doubling (Cas où P = Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (3x^2 + a) / 2y
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Point Addition (Cas où P != Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (y2 - y1) / (x2 - x1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">lambda&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">x3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y3&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="83-implémentation-du-conditional-swap-en-temps-constant">8.3. Implémentation du Conditional Swap en temps constant
&lt;/h3>&lt;p>Lors de l&amp;rsquo;échange du contenu des variables basé sur la valeur du bit de la clé privée, nous effectuons l&amp;rsquo;échange uniquement avec des opérations bit à bit (masque) sans utiliser l&amp;rsquo;instruction &lt;code>if&lt;/code>. Cela garantit que le chemin d&amp;rsquo;exécution reste parfaitement constant.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
Dans une implémentation réelle, une classe d&amp;rsquo;entiers à précision multiple allouée dynamiquement comme &lt;code>cpp_int&lt;/code> ne convient pas au traitement en temps constant. En effet, des informations temporelles fuient en raison des allocations de mémoire et des variations de taille des tableaux. Les bibliothèques pratiques les représentent sous forme de taille fixe (par exemple, un tableau de uint64_t × 4 éléments) et implémentent le traitement des masques au niveau du bit. Voici un exemple conceptuel.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Conditional Swap conceptuel en temps constant (supposant des entiers de taille fixe)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Si le bit est 1, échanger P1 et P2, sinon ne pas échanger
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// bit vaut 0 ou 1. Le masque est tout à 1 (0xFF..) si bit=1, et tout à 0 si bit=0.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (Ici pour l&amp;#39;explication, nous supposons que chaque mot de la classe BigInt de taille fixe est w)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="cm">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t mask = 0 - (uint64_t)bit;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> for (int i = 0; i &amp;lt; NUM_WORDS; i++) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t dummy = mask &amp;amp; (P1.x.words[i] ^ P2.x.words[i]);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P1.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P2.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> // Traiter les coordonnées y et le drapeau isInfinity de la même manière
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// * Un échange parfait en temps constant est difficile avec boost::multiprecision,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// donc nous nous limitons ici à une simulation par branchement pour la compréhension de la logique.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="84-multiplication-scalaire-avec-léchelle-de-montgomery">8.4. Multiplication scalaire avec l&amp;rsquo;échelle de Montgomery
&lt;/h3>&lt;p>En combinant les &lt;code>pointAdd&lt;/code> et &lt;code>cswap&lt;/code> précédents, nous implémentons une multiplication scalaire sécurisée.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Multiplication scalaire k * P (Méthode Montgomery Ladder)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">scalarMultiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Point&lt;/span> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// Point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Obtenir la longueur en bits de k (256 bits pour secp256k1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Obtenir la valeur du i-ème bit (0 ou 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bit_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si bit == 1, échanger R0 et R1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Toujours exécuter les mêmes opérations (Point Addition et Point Doubling)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si bit == 1, échanger à nouveau pour restaurer l&amp;#39;état
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Avec cette logique d&amp;rsquo;implémentation, que chaque bit du scalaire $k$ soit &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, les opérations exécutées dans chaque itération de la boucle (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) suivent exactement le même flux. Cela empêche efficacement la fuite d&amp;rsquo;informations secrètes via des différences de timing ou de modèles d&amp;rsquo;accès au cache.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion">9. Conclusion
&lt;/h2>&lt;p>La cryptographie sur les courbes elliptiques (ECC) peut sembler mystérieuse à première vue : &amp;ldquo;Comment une opération géométrique consistant à tracer une droite et refléter son intersection peut-elle devenir une cryptographie ?&amp;rdquo;. Cependant, en la mappant sur le monde discret des corps finis, on peut construire une magnifique fonction à sens unique (problème du logarithme discret), fruit d&amp;rsquo;une fusion miraculeuse entre les mathématiques et la cryptographie.&lt;/p>
&lt;p>Cet article a expliqué les points importants suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Supériorité par rapport à RSA&lt;/strong> : Offre une sécurité forte avec une taille de clé très courte, ce qui est optimal pour l&amp;rsquo;ère moderne du mobile et de l&amp;rsquo;IoT.&lt;/li>
&lt;li>&lt;strong>Fondements de la théorie des groupes et des corps finis&lt;/strong> : Les structures mathématiques sur lesquelles repose l&amp;rsquo;ECC.&lt;/li>
&lt;li>&lt;strong>Formules d&amp;rsquo;addition et de doublement&lt;/strong> : Méthode d&amp;rsquo;implémentation des opérations algébriques de groupe à l&amp;rsquo;aide de l&amp;rsquo;équation de Weierstrass.&lt;/li>
&lt;li>&lt;strong>Menace des attaques par canaux auxiliaires&lt;/strong> : Le fait que les branchements conditionnels dépendants des bits de la clé privée créent une vulnérabilité fatale.&lt;/li>
&lt;li>&lt;strong>Implémentation en temps constant (Constant-Time)&lt;/strong> : Technique de codage en C++ pour homogénéiser le comportement au niveau matériel et prévenir les attaques à l&amp;rsquo;aide du Montgomery Ladder et du Conditional Swap.&lt;/li>
&lt;/ol>
&lt;p>Écrire soi-même une bibliothèque cryptographique fonctionnant en environnement de production est fortement déconseillé (&amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;) car les risques de sécurité sont extrêmement élevés. Cependant, comprendre en profondeur les algorithmes et le contexte mathématique qui fonctionnent en son sein devrait être une arme incroyablement puissante pour les ingénieurs concevant et exploitant des systèmes plus sécurisés et plus performants.&lt;/p>
&lt;p>Dans le prochain article, nous approfondirons le mécanisme de l&amp;rsquo;&lt;strong>ECDSA (Elliptic Curve Digital Signature Algorithm)&lt;/strong>, un algorithme de signature numérique utilisant ces courbes elliptiques, ainsi que les &lt;strong>signatures de Schnorr&lt;/strong> adoptées par Bitcoin.&lt;/p></description></item></channel></rss>