<?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/categories/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 22:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/categories/cryptography/index.xml" rel="self" type="application/rss+xml"/><item><title>Fondements et implémentation de la cryptographie à l'aide du petit théorème de Fermat</title><link>http://kenji.blog/fr/p/fermats-little-theorem-cryptography-implementation/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/fermats-little-theorem-cryptography-implementation/</guid><description>&lt;img src="http://kenji.blog/p/fermats-little-theorem-cryptography-implementation/img/eyecatch.jpg" alt="Featured image of post Fondements et implémentation de la cryptographie à l'aide du petit théorème de Fermat" />&lt;h2 id="1-introduction--le-mystère-mathématique-qui-sous-tend-la-cryptographie-moderne">1. Introduction : Le mystère mathématique qui sous-tend la cryptographie moderne
&lt;/h2>&lt;p>Dans la société numérique d&amp;rsquo;aujourd&amp;rsquo;hui, et particulièrement dans les communications sur Internet, le &amp;ldquo;chiffrement&amp;rdquo; est devenu une technologie fondamentale indispensable. Le fait que nous puissions naviguer en toute sécurité sur des sites web via HTTPS dans nos navigateurs, effectuer des transactions financières par le biais des services bancaires en ligne, et avoir des échanges privés sur des applications de messagerie est dû aux protocoles cryptographiques basés sur des théories mathématiques avancées fonctionnant en arrière-plan. Parmi ceux-ci, la &amp;ldquo;cryptographie à clé publique&amp;rdquo; joue un rôle particulièrement important, dont le représentant le plus célèbre est le &lt;strong>chiffrement RSA&lt;/strong>.&lt;/p>
&lt;p>La sécurité et la validité de nombreux algorithmes cryptographiques, y compris RSA, dépendent fortement d&amp;rsquo;un théorème extrêmement beau et puissant découvert par le mathématicien français du 17e siècle, Pierre de Fermat. Il s&amp;rsquo;agit du &lt;strong>petit théorème de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>. De plus, le théorème de Leonhard Euler, qui généralise ce théorème, joue également un rôle décisif dans la théorie cryptographique.&lt;/p>
&lt;p>Cet article explique en détail, depuis les bases, comment la découverte mathématique pure qu&amp;rsquo;est le petit théorème de Fermat s&amp;rsquo;applique aux technologies cryptographiques pratiques modernes, en particulier aux &amp;ldquo;tests de primalité&amp;rdquo; et au &amp;ldquo;chiffrement RSA&amp;rdquo;. Il s&amp;rsquo;agit d&amp;rsquo;un guide technique très détaillé couvrant tout, des preuves mathématiques, aux mécanismes de chiffrement et de déchiffrement, jusqu&amp;rsquo;à l&amp;rsquo;implémentation concrète des algorithmes en C++ et Python.&lt;/p>
&lt;hr>
&lt;h2 id="2-bases-des-congruences-et-de-larithmétique-modulaire">2. Bases des congruences et de l&amp;rsquo;arithmétique modulaire
&lt;/h2>&lt;p>Pour comprendre le petit théorème de Fermat, vous devez d&amp;rsquo;abord vous familiariser avec le concept mathématique d&amp;rsquo;&amp;ldquo;arithmétique modulaire (congruences)&amp;rdquo;. L&amp;rsquo;arithmétique modulaire est un système de calcul qui se concentre sur le &amp;ldquo;reste&amp;rdquo; lorsqu&amp;rsquo;un nombre est divisé par un nombre fixe (appelé module). Comme il s&amp;rsquo;agit d&amp;rsquo;un calcul similaire à celui du cadran d&amp;rsquo;une horloge (qui fait un tour en 12 heures), on l&amp;rsquo;appelle aussi parfois &amp;ldquo;mathématiques de l&amp;rsquo;horloge&amp;rdquo;.&lt;/p>
&lt;p>Lorsque le reste de la division de deux entiers $a$ et $b$ par un entier positif $n$ est égal, on l&amp;rsquo;écrit mathématiquement comme suit :&lt;/p>
$$
a \equiv b \pmod n
$$
&lt;p>Cela se lit &amp;ldquo;$a$ et $b$ sont congrus modulo $n$&amp;rdquo;. Par exemple, le reste de 17 divisé par 5 est 2, et le reste de 12 divisé par 5 est également 2. Par conséquent, on peut écrire ce qui suit :&lt;/p>
$$
17 \equiv 12 \pmod 5 \equiv 2 \pmod 5
$$
&lt;p>En arithmétique modulaire, les quatre opérations arithmétiques habituelles (addition, soustraction, multiplication) s&amp;rsquo;appliquent telles quelles.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition&lt;/strong> : Si $a \equiv b \pmod n$ et $c \equiv d \pmod n$, alors $a + c \equiv b + d \pmod n$&lt;/li>
&lt;li>&lt;strong>Soustraction&lt;/strong> : Si $a \equiv b \pmod n$ et $c \equiv d \pmod n$, alors $a - c \equiv b - d \pmod n$&lt;/li>
&lt;li>&lt;strong>Multiplication&lt;/strong> : Si $a \equiv b \pmod n$ et $c \equiv d \pmod n$, alors $a \times c \equiv b \times d \pmod n$&lt;/li>
&lt;li>&lt;strong>Exponentiation&lt;/strong> : Si $a \equiv b \pmod n$, alors pour tout entier naturel $k$, $a^k \equiv b^k \pmod n$&lt;/li>
&lt;/ol>
&lt;p>Cependant, il faut faire attention à la &lt;strong>division&lt;/strong>. En général, même si $a \times c \equiv b \times c \pmod n$, vous ne pouvez pas diviser les deux côtés par $c$ pour obtenir $a \equiv b \pmod n$. Cela n&amp;rsquo;est vrai que si $c$ et $n$ sont premiers entre eux (leur plus grand commun diviseur est 1). Ce concept d&amp;rsquo;&amp;ldquo;inverse modulaire&amp;rdquo; devient extrêmement important dans la génération de clés pour le chiffrement RSA, que nous aborderons plus tard.&lt;/p>
&lt;hr>
&lt;h2 id="3-contexte-mathématique-et-preuve-du-petit-théorème-de-fermat">3. Contexte mathématique et preuve du petit théorème de Fermat
&lt;/h2>&lt;p>Maintenant que nous avons couvert les bases de l&amp;rsquo;arithmétique modulaire, examinons le sujet principal, le petit théorème de Fermat.&lt;/p>
&lt;h3 id="31-définition-du-théorème">3.1 Définition du théorème
&lt;/h3>&lt;p>Le petit théorème de Fermat est formulé comme suit :&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Petit théorème de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>
Soit $p$ un nombre premier et $a$ un entier quelconque qui n&amp;rsquo;est pas un multiple de $p$ (c&amp;rsquo;est-à-dire que $a$ et $p$ sont premiers entre eux). Alors, la congruence suivante est vraie :
&lt;/p>
$$ a^{p-1} \equiv 1 \pmod p $$
&lt;/blockquote>
&lt;p>Il est également courant d&amp;rsquo;exprimer ce théorème sous une forme valable pour tout entier $a$, en supprimant la condition &amp;ldquo;$a$ n&amp;rsquo;est pas un multiple de $p$&amp;rdquo;. Dans ce cas, on multiplie les deux côtés par $a$, ce qui donne :&lt;/p>
$$
a^p \equiv a \pmod p
$$
&lt;h3 id="32-vérification-par-des-exemples-concrets">3.2 Vérification par des exemples concrets
&lt;/h3>&lt;p>Vérifions si le théorème se vérifie vraiment en utilisant des nombres concrets.
Soit le nombre premier $p = 5$. Alors $p-1 = 4$. Nous choisissons un entier pour $a$ qui n&amp;rsquo;est pas un multiple de $p$.&lt;/p>
&lt;ul>
&lt;li>Pour $a = 2$ : $2^{5-1} = 2^4 = 16$. $16 \div 5 = 3$ avec un reste de $1$. Donc $16 \equiv 1 \pmod 5$. (Vérifié)&lt;/li>
&lt;li>Pour $a = 3$ : $3^{5-1} = 3^4 = 81$. $81 \div 5 = 16$ avec un reste de $1$. Donc $81 \equiv 1 \pmod 5$. (Vérifié)&lt;/li>
&lt;li>Pour $a = 4$ : $4^{5-1} = 4^4 = 256$. $256 \div 5 = 51$ avec un reste de $1$. Donc $256 \equiv 1 \pmod 5$. (Vérifié)&lt;/li>
&lt;/ul>
&lt;p>Ainsi, quel que soit le $a$ que vous choisissez (à condition qu&amp;rsquo;il ne soit pas un multiple de 5), le reste de sa 4ème puissance divisée par 5 sera toujours 1. Cela ressemble à de la magie, mais cela découle des magnifiques propriétés des nombres premiers.&lt;/p>
&lt;h3 id="33-preuve-mathématique-du-théorème">3.3 Preuve mathématique du théorème
&lt;/h3>&lt;p>Pourquoi cela est-il vrai ? Nous présentons ici une preuve élégante utilisant l&amp;rsquo;ensemble des classes de restes.&lt;/p>
&lt;p>Considérons l&amp;rsquo;ensemble $S = \{1, 2, 3, \dots, p-1\}$. Ce sont les représentants des entiers dont les restes de la division par $p$ vont de $1$ à $p-1$.
Considérons maintenant un nouvel ensemble $T$ obtenu en multipliant chaque élément par un entier $a$ qui est premier avec $p$.
&lt;/p>
$$ T = \{1a, 2a, 3a, \dots, (p-1)a\} $$
&lt;p>Considérons les restes de chaque élément de cet ensemble $T$ divisé par $p$. Étonnamment, ces restes, bien que leur ordre puisse changer, correspondent exactement à l&amp;rsquo;ensemble des éléments de l&amp;rsquo;ensemble d&amp;rsquo;origine $S$.
Pourquoi ?&lt;/p>
&lt;ol>
&lt;li>Les éléments de $T$ ne peuvent jamais être des multiples de $p$ (car ni $a$ ni les éléments d&amp;rsquo;origine ne sont des multiples de $p$).&lt;/li>
&lt;li>Il n&amp;rsquo;y a pas deux éléments distincts dans $T$ qui sont congrus modulo $p$. Si $ia \equiv ja \pmod p$ ($i \neq j$), puisque $a$ et $p$ sont premiers entre eux, nous pouvons diviser par $a$ pour obtenir $i \equiv j \pmod p$, ce qui est une contradiction.&lt;/li>
&lt;/ol>
&lt;p>Par conséquent, le produit de tous les éléments de $S$ et le produit de tous les éléments de $T$ sont congrus modulo $p$.&lt;/p>
$$
(1a) \times (2a) \times \dots \times ((p-1)a) \equiv 1 \times 2 \times \dots \times (p-1) \pmod p
$$
&lt;p>En réorganisant le côté gauche, puisqu&amp;rsquo;il y a $p-1$ termes de $a$,&lt;/p>
$$
a^{p-1} \cdot (p-1)! \equiv (p-1)! \pmod p
$$
&lt;p>Comme $(p-1)!$ est premier avec $p$, nous pouvons diviser les deux côtés par $(p-1)!$, ce qui conduit finalement au théorème suivant :&lt;/p>
$$
a^{p-1} \equiv 1 \pmod p
$$
&lt;p>Ceci est la preuve du petit théorème de Fermat.&lt;/p>
&lt;hr>
&lt;h2 id="4-la-fonction-indicatrice-deuler-et-le-théorème-deuler">4. La fonction indicatrice d&amp;rsquo;Euler et le théorème d&amp;rsquo;Euler
&lt;/h2>&lt;p>Le petit théorème de Fermat est un théorème concernant &amp;ldquo;un nombre premier $p$&amp;rdquo;, mais il a été généralisé à &amp;ldquo;tout entier positif $n$&amp;rdquo; par Leonhard Euler. Cette extension est essentielle pour comprendre le chiffrement RSA.&lt;/p>
&lt;h3 id="41-la-fonction-indicatrice-deuler-phin">4.1 La fonction indicatrice d&amp;rsquo;Euler $\phi(n)$
&lt;/h3>&lt;p>La fonction indicatrice d&amp;rsquo;Euler (ou fonction $\phi$ d&amp;rsquo;Euler) $\phi(n)$ est une fonction qui représente &amp;ldquo;le nombre d&amp;rsquo;entiers de $1$ à $n$ qui sont premiers avec $n$&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>Dans le cas d&amp;rsquo;un nombre premier $p$, puisque tous les entiers de $1$ à $p-1$ sont premiers avec $p$, $\phi(p) = p - 1$.&lt;/li>
&lt;li>Pour le produit de deux nombres premiers distincts $p$ et $q$, c&amp;rsquo;est-à-dire $n = p \times q$, $\phi(n)$ peut être calculé avec une formule très simple :
$$ \phi(p \times q) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$&lt;/li>
&lt;/ul>
&lt;p>Cette propriété est la logique fondamentale derrière la génération de clés dans le chiffrement RSA.&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>Euler a généralisé le petit théorème de Fermat comme suit :&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Théorème d&amp;rsquo;Euler (Euler&amp;rsquo;s Theorem)&lt;/strong>
Pour tout entier positif $n$ et tout entier $a$ qui lui est premier entre eux, ce qui suit est vrai :
&lt;/p>
$$ a^{\phi(n)} \equiv 1 \pmod n $$
&lt;/blockquote>
&lt;p>Si $n$ est un nombre premier $p$, alors $\phi(p) = p - 1$, donc cela devient exactement le petit théorème de Fermat ($a^{p-1} \equiv 1 \pmod p$). En d&amp;rsquo;autres termes, le petit théorème de Fermat n&amp;rsquo;est qu&amp;rsquo;un cas particulier du théorème d&amp;rsquo;Euler.&lt;/p>
&lt;hr>
&lt;h2 id="5-trouver-dénormes-nombres-premiers--le-test-de-primalité-de-fermat">5. Trouver d&amp;rsquo;énormes nombres premiers : Le test de primalité de Fermat
&lt;/h2>&lt;p>Dans les technologies cryptographiques (comme le chiffrement RSA et l&amp;rsquo;échange de clés Diffie-Hellman), il est nécessaire de trouver rapidement &amp;ldquo;d&amp;rsquo;énormes nombres premiers&amp;rdquo; s&amp;rsquo;étendant sur des centaines de chiffres. Cependant, utiliser la méthode de la &amp;ldquo;division par essais&amp;rdquo;, qui consiste à essayer de diviser par tous les nombres de $2$ à $\sqrt{N}$ pour déterminer si un grand nombre $N$ est premier, prendrait un temps équivalent à l&amp;rsquo;âge de l&amp;rsquo;univers.&lt;/p>
&lt;p>C&amp;rsquo;est là qu&amp;rsquo;intervient le &lt;strong>test de primalité de Fermat (Fermat Primality Test)&lt;/strong>, un &amp;ldquo;test de primalité probabiliste&amp;rdquo; qui utilise le petit théorème de Fermat à l&amp;rsquo;envers.&lt;/p>
&lt;h3 id="51-quest-ce-quun-test-de-primalité-probabiliste-">5.1 Qu&amp;rsquo;est-ce qu&amp;rsquo;un test de primalité probabiliste ?
&lt;/h3>&lt;p>Selon le petit théorème de Fermat, si $p$ est premier, alors $a^{p-1} \equiv 1 \pmod p$ est toujours vrai pour tout $a$ ($1 &lt; a &lt; p$).
La contraposée de cette affirmation est : &amp;ldquo;S&amp;rsquo;il existe un $a$ pour lequel $a^{p-1} \not\equiv 1 \pmod p$, alors $p$ &lt;strong>n&amp;rsquo;est absolument pas un nombre premier (c&amp;rsquo;est un nombre composé)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>Par conséquent, si vous voulez déterminer si $N$ est premier, vous choisissez quelques valeurs aléatoires de $a$, calculez $a^{N-1} \pmod N$ et vérifiez si le résultat est $1$. Si vous obtenez une réponse autre que $1$ ne serait-ce qu&amp;rsquo;une seule fois, il est certain que $N$ est un nombre composé. S&amp;rsquo;il vaut $1$ peu importe le nombre de fois que vous essayez, vous pouvez juger avec une forte probabilité que $N$ est &amp;ldquo;probablement premier&amp;rdquo;.&lt;/p>
&lt;h3 id="52-explication-de-lalgorithme-et-organigramme">5.2 Explication de l&amp;rsquo;algorithme et organigramme
&lt;/h3>&lt;p>L&amp;rsquo;algorithme du test de Fermat est le suivant :&lt;/p>
&lt;div class="mermaid">flowchart TD
Start["Début"] --> Input["Entrer le nombre à tester p et le nombre de tests k"]
Input --> LoopStart["Boucle de i = 0 à k-1"]
LoopStart --> Condition{"i &lt; k ?"}
Condition -- "Oui" --> RandomA["Choisir un entier aléatoire a dans la plage 1 &lt; a &lt; p-1"]
RandomA --> Calc["Calculer l'exponentiation modulaire a^(p-1) mod p"]
Calc --> CheckPrime{"Le résultat est-il 1 ?"}
CheckPrime -- "Non" --> ReturnComposite["p est un nombre composé (certain)"]
CheckPrime -- "Oui" --> Increment["Incrémenter i"]
Increment --> Condition
Condition -- "Non" --> ReturnPrime["p est probablement premier (probabiliste)"]
ReturnComposite --> End["Fin"]
ReturnPrime --> End&lt;/div>
&lt;h3 id="53-le-piège-des-nombres-de-carmichael-pseudo-premiers">5.3 Le piège des nombres de Carmichael (pseudo-premiers)
&lt;/h3>&lt;p>Bien que le test de Fermat soit extrêmement rapide, il présente un défaut majeur. Il existe des nombres diaboliques qui, bien qu&amp;rsquo;ils soient composés, satisfont $a^{N-1} \equiv 1 \pmod N$ pour tous les $a$. Ceux-ci sont appelés &lt;strong>nombres de Carmichael (Carmichael numbers)&lt;/strong>. Le plus petit nombre de Carmichael est $561$ ($3 \times 11 \times 17$).&lt;/p>
&lt;p>En raison de l&amp;rsquo;existence des nombres de Carmichael, un test de Fermat pur seul ne peut pas déterminer la primalité de manière absolue. C&amp;rsquo;est pourquoi, dans les systèmes cryptographiques réels (comme OpenSSL), le &lt;strong>test de primalité de Miller-Rabin (Miller-Rabin primality test)&lt;/strong>, qui est une version améliorée du test de Fermat, est utilisé en standard. Le test de Miller-Rabin peut détecter les nombres de Carmichael, réduisant ainsi la probabilité de fausse détection à presque zéro.&lt;/p>
&lt;h3 id="54-exponentiation-modulaire-rapide-méthode-dexponentiation-par-carrés">5.4 Exponentiation modulaire rapide (Méthode d&amp;rsquo;exponentiation par carrés)
&lt;/h3>&lt;p>Dans l&amp;rsquo;algorithme de test de primalité, il est nécessaire de calculer $a^{N-1} \pmod N$. Si $N$ est énorme, $a^{N-1}$ aura un nombre de chiffres astronomique et ne tiendra pas dans la mémoire d&amp;rsquo;un ordinateur.
La solution à ce problème est la &lt;strong>méthode d&amp;rsquo;exponentiation par carrés (Exponentiation by Squaring)&lt;/strong> ou exponentiation modulaire. En prenant le modulo (mod N) à chaque étape du calcul, la valeur est toujours maintenue plus petite que $N$, ce qui permet un calcul très rapide (complexité temporelle $O(\log N)$).&lt;/p>
&lt;hr>
&lt;h2 id="6-implémentation-du-test-de-primalité-et-de-lexponentiation-modulaire">6. Implémentation du test de primalité et de l&amp;rsquo;exponentiation modulaire
&lt;/h2>&lt;p>Maintenant, implémentons le test de primalité de Fermat et la méthode d&amp;rsquo;exponentiation par carrés en C++ et Python.&lt;/p>
&lt;h3 id="61-implémentation-en-c">6.1 Implémentation en C++
&lt;/h3>&lt;p>En C++, les types d&amp;rsquo;entiers standard ont tendance à déborder facilement, donc une bibliothèque d&amp;rsquo;entiers à précision multiple (comme GMP) est nécessaire pour manipuler des nombres géants. Cependant, pour comprendre l&amp;rsquo;algorithme, nous montrons ici une implémentation dans la limite des entiers 64 bits (&lt;code>unsigned long long&lt;/code>).&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;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&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;random&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">std&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">// Exponentiation modulaire rapide (a^b mod m) - Exponentiation par carrés
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&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="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">result&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">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&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">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&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="c1">// Si le bit de poids faible de b est 1, multiplier le résultat par a
&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">b&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="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="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Extension en 128 bits pour éviter le débordement
&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="c1">// Élever a au carré
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&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">a&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="c1">// Décaler b vers la droite (diviser par la moitié)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">b&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">result&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">// Test de primalité 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="kt">bool&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">iterations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&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="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&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="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&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="o">%&lt;/span> &lt;span class="mi">2&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="nb">false&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">random_device&lt;/span> &lt;span class="n">rd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mt19937_64&lt;/span> &lt;span class="n">gen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rd&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uniform_int_distribution&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">dis&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">p&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>&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">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&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="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gen&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si a^(p-1) mod p n&amp;#39;est pas 1, alors c&amp;#39;est un nombre composé
&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">power_mod&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">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">p&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="k">return&lt;/span> &lt;span class="nb">false&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;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Probablement premier
&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="kt">int&lt;/span> &lt;span class="nf">main&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="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000000007&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Nombre premier connu
&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">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is probably prime.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&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="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is composite.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&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="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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-implémentation-en-python">6.2 Implémentation en Python
&lt;/h3>&lt;p>En Python, le type entier standard prend en charge les entiers à précision multiple, il n&amp;rsquo;y a donc pas besoin de s&amp;rsquo;inquiéter du débordement. De plus, la fonction intégrée &lt;code>pow(a, b, m)&lt;/code> de Python utilise l&amp;rsquo;exponentiation par carrés en interne et est très rapide.&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="kn">import&lt;/span> &lt;span class="nn">random&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">fermat_is_prime&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">iterations&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&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;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Test de primalité probabiliste utilisant le test de Fermat
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&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">p&lt;/span> &lt;span class="o">&amp;lt;=&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="k">return&lt;/span> &lt;span class="kc">False&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">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&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="kc">True&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">p&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">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">return&lt;/span> &lt;span class="kc">False&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">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Choisir un nombre aléatoire a entre 2 et p-2&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">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">2&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">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculer a^(p-1) mod p. La fonction intégrée pow est rapide.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">pow&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">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">p&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># Certitude que c&amp;#39;est un nombre composé&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="kc">True&lt;/span> &lt;span class="c1"># Probablement premier&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"># Test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">number_to_test&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">104729&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">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&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;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> est probablement premier.&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">else&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;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> est un nombre composé.&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;hr>
&lt;h2 id="7-application-au-chiffrement-rsa--où-fermat-et-euler-se-rencontrent">7. Application au chiffrement RSA : Où Fermat et Euler se rencontrent
&lt;/h2>&lt;p>La plus grande application du petit théorème de Fermat (et du théorème d&amp;rsquo;Euler) est le &lt;strong>chiffrement RSA&lt;/strong>, développé en 1977 par Rivest, Shamir et Adleman.
Le chiffrement RSA est un système révolutionnaire de &amp;ldquo;cryptographie à clé publique&amp;rdquo;, qui réalise un mécanisme où la clé de chiffrement (clé publique) est rendue publique au monde entier, tandis que la clé de déchiffrement (clé privée) n&amp;rsquo;est connue que du destinataire.&lt;/p>
&lt;p>Cette asymétrie repose sur la sécurité computationnelle selon laquelle &amp;ldquo;la factorisation en nombres premiers de nombres composés géants est extrêmement difficile&amp;rdquo;.&lt;/p>
&lt;h3 id="71-fonctionnement-du-chiffrement-rsa-génération-de-clés-chiffrement-déchiffrement">7.1 Fonctionnement du chiffrement RSA (Génération de clés, Chiffrement, Déchiffrement)
&lt;/h3>&lt;p>Vérifions le flux de communication global du chiffrement RSA avec un diagramme de séquence Mermaid.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice["Alice (Destinataire)"]
participant Bob["Bob (Expéditeur)"]
Alice->>Alice: "Générer d'énormes nombres premiers p, q"
Alice->>Alice: "Calculer N = p * q, φ(N) = (p-1)(q-1)"
Alice->>Alice: "Calculer la clé publique e et la clé privée d (e*d ≡ 1 mod φ(N))"
Alice->>Bob: "Envoyer la clé publique (N, e)"
Note over Bob: "Préparer le texte clair M (M &lt; N)"
Bob->>Bob: "Calculer le texte chiffré C = M^e mod N"
Bob->>Alice: "Envoyer le texte chiffré C"
Alice->>Alice: "Calculer le texte clair M = C^d mod N pour déchiffrer"&lt;/div>
&lt;p>Voici une explication des étapes mathématiques détaillées.&lt;/p>
&lt;h4 id="étape-1--génération-de-clés-travail-du-destinataire-alice">Étape 1 : Génération de clés (Travail du destinataire Alice)
&lt;/h4>&lt;ol>
&lt;li>Générer aléatoirement deux énormes nombres premiers $p$ et $q$ (c&amp;rsquo;est là que la méthode de test de primalité mentionnée ci-dessus est utilisée).&lt;/li>
&lt;li>Calculer leur produit $N = p \times q$. Ce $N$ est rendu public.&lt;/li>
&lt;li>En utilisant la fonction indicatrice d&amp;rsquo;Euler, calculer $\phi(N) = (p-1)(q-1)$.&lt;/li>
&lt;li>Choisir un entier $e$ (exposant public) qui est premier avec $\phi(N)$ (souvent $e = 65537$ est utilisé).&lt;/li>
&lt;li>Calculer l&amp;rsquo;inverse modulaire $d$ (exposant privé) de $e$. C&amp;rsquo;est-à-dire, trouver $d$ qui satisfait ce qui suit :
$$ e \cdot d \equiv 1 \pmod{\phi(N)} $$
&lt;strong>L&amp;rsquo;algorithme d&amp;rsquo;Euclide étendu&lt;/strong> est utilisé pour ce calcul.&lt;/li>
&lt;/ol>
&lt;p>La &lt;strong>clé publique est maintenant $(N, e)$&lt;/strong> et la &lt;strong>clé privée est $(N, d)$&lt;/strong>. ($p$, $q$, et $\phi(N)$ doivent être immédiatement détruits ou strictement dissimulés).&lt;/p>
&lt;h4 id="étape-2--chiffrement-travail-de-lexpéditeur-bob">Étape 2 : Chiffrement (Travail de l&amp;rsquo;expéditeur Bob)
&lt;/h4>&lt;p>Supposons que Bob veuille envoyer un message $M$ à Alice ($M$ est la version numérisée des caractères, avec $0 \le M &lt; N$).
Bob utilise la clé publique d&amp;rsquo;Alice $(N, e)$ pour effectuer le calcul suivant et créer le texte chiffré $C$.&lt;/p>
$$
C \equiv M^e \pmod N
$$
&lt;p>Ce $C$ est envoyé à Alice via le réseau.&lt;/p>
&lt;h4 id="étape-3--déchiffrement-travail-du-destinataire-alice">Étape 3 : Déchiffrement (Travail du destinataire Alice)
&lt;/h4>&lt;p>Alice, après avoir reçu le texte chiffré $C$, effectue le calcul suivant en utilisant sa clé privée $d$, qu&amp;rsquo;elle seule connaît.&lt;/p>
$$
M' \equiv C^d \pmod N
$$
&lt;p>Étonnamment, ce résultat de calcul $M'$ correspond parfaitement au message original $M$.&lt;/p>
&lt;h3 id="72-pourquoi-cela-peut-il-être-déchiffré--preuve-mathématique">7.2 Pourquoi cela peut-il être déchiffré ? (Preuve mathématique)
&lt;/h3>&lt;p>C&amp;rsquo;est ici que le petit théorème de Fermat (le théorème d&amp;rsquo;Euler) montre sa véritable valeur. Pourquoi $C^d \pmod N$ revient-il à $M$ ?&lt;/p>
&lt;p>Développons la formule de déchiffrement.
Puisque $C \equiv M^e \pmod N$,
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Lors de l&amp;rsquo;étape de génération de clés, nous avons choisi $d$ de sorte que $e \cdot d \equiv 1 \pmod{\phi(N)}$. Cela signifie qu&amp;rsquo;il existe un entier $k$ tel qu&amp;rsquo;il peut s&amp;rsquo;écrire comme suit :
&lt;/p>
$$ e \cdot d = 1 + k \cdot \phi(N) $$
&lt;p>En substituant cela dans la formule ci-dessus :
&lt;/p>
$$ M^{ed} = M^{1 + k \cdot \phi(N)} = M \cdot M^{k \cdot \phi(N)} = M \cdot (M^{\phi(N)})^k \pmod N $$
&lt;p>Ici, le &lt;strong>théorème d&amp;rsquo;Euler&lt;/strong> ($M^{\phi(N)} \equiv 1 \pmod N$) entre en jeu. (&lt;em>Strictement parlant, $M$ et $N$ doivent être premiers entre eux, mais dans RSA, la probabilité que $M$ et $N$ ne soient pas premiers entre eux est astronomiquement faible, et en utilisant le théorème des restes chinois, il peut être prouvé que cela est vrai même s&amp;rsquo;ils ne sont pas premiers entre eux&lt;/em>).&lt;/p>
&lt;p>En appliquant le théorème d&amp;rsquo;Euler, puisque $M^{\phi(N)} \equiv 1$,
&lt;/p>
$$ M \cdot (1)^k \equiv M \pmod N $$
&lt;p>$M$ est magnifiquement restauré ! Les propriétés des nombres que Fermat et Euler ont découvertes il y a des centaines d&amp;rsquo;années garantissent parfaitement la confidentialité des communications numériques modernes.&lt;/p>
&lt;hr>
&lt;h2 id="8-implémentation-jouet-du-chiffrement-rsa-python">8. Implémentation jouet du chiffrement RSA (Python)
&lt;/h2>&lt;p>Comme il est difficile de saisir cela uniquement en théorie, utilisons Python pour implémenter réellement le processus de génération de clés, de chiffrement et de déchiffrement RSA. Bien qu&amp;rsquo;il s&amp;rsquo;agisse d&amp;rsquo;une &amp;ldquo;implémentation jouet&amp;rdquo; à des fins éducatives, les mathématiques utilisées sont exactement les mêmes que les vraies.&lt;/p>
&lt;p>Nous inclurons également une implémentation de &amp;ldquo;l&amp;rsquo;algorithme d&amp;rsquo;Euclide étendu&amp;rdquo; pour trouver l&amp;rsquo;inverse modulaire $d$.&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;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&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="kn">import&lt;/span> &lt;span class="nn">random&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"># Trouver le plus grand commun diviseur&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">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="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="c1"># Algorithme d&amp;#39;Euclide étendu (trouver x, y pour ax + by = gcd(a,b))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Utilisé pour trouver d pour e*d ≡ 1 (mod φ(N))&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">extended_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="k">if&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">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&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">1&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">g&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">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&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">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&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="p">(&lt;/span>&lt;span class="n">g&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">b&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">a&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">y&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">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="n">g&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="o">=&lt;/span> &lt;span class="n">extended_gcd&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">g&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="k">raise&lt;/span> &lt;span class="ne">Exception&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;L&amp;#39;inverse n&amp;#39;existe pas&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">else&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">x&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="c1"># Fonction de génération de nombres premiers (Version simplifiée : génère de petits nombres premiers)&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">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&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="kc">True&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&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">getrandbits&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Jugement simplifié au lieu du test de Fermat mentionné ci-dessus&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">p&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&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">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">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&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="n">p&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">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"># Génération de clés RSA&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">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&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="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># S&amp;#39;assurer que p et q ne sont pas identiques&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">p&lt;/span> &lt;span class="o">==&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="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&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">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="c1"># e est souvent un nombre premier comme 65537, mais ici il est choisi aléatoirement&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">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&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 class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&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">while&lt;/span> &lt;span class="n">g&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="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&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 class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&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="c1"># Calcul de la clé privée d&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="c1"># Clé publique (e, n), Clé privée (d, n)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&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 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="k">def&lt;/span> &lt;span class="nf">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">plaintext&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="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculer plaintext^e mod n&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cipher&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">pow&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="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 class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">plaintext&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">cipher&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">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">):&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">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculer cipher^d mod n et reconvertir en caractères&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">plain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">chr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&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 class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ciphertext&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="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plain&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 d&amp;#39;exécution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&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="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;--- Implémentation jouet du chiffrement RSA ---&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">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">private_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># Utilisation de nombres premiers de 12 bits&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, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">public_key&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, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">private_key&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">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Hello Math!&amp;#34;&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;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Message d&amp;#39;origine : &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;#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&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">encrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message&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">encrypted_msg&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"># Déchiffrement&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encrypted_msg&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_msg&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>Lorsque vous exécutez ce code, vous pouvez voir le tableau de caractères être converti en un tableau de nombres peu familiers (texte chiffré), qui est ensuite magnifiquement restauré en la chaîne d&amp;rsquo;origine par la clé privée.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion--lintersection-de-la-beauté-mathématique-et-de-la-praticité">9. Conclusion : L&amp;rsquo;intersection de la beauté mathématique et de la praticité
&lt;/h2>&lt;p>Au 17ème siècle, lorsque Pierre de Fermat a découvert ce &amp;ldquo;petit théorème&amp;rdquo;, personne ne pensait qu&amp;rsquo;il serait utile à quoi que ce soit. Fermat lui-même a mené des recherches en théorie des nombres par pure curiosité mathématique.&lt;/p>
&lt;p>Cependant, environ 300 ans plus tard, dans les années 1970, à l&amp;rsquo;aube des réseaux informatiques, le théorème de Fermat a fait un retour spectaculaire en tant que technologie cryptographique essentielle pour l&amp;rsquo;établissement de protocoles de communication sécurisés. La technologie de test de primalité basée sur le petit théorème de Fermat et le chiffrement RSA basé sur le théorème d&amp;rsquo;Euler soutiennent littéralement l&amp;rsquo;infrastructure Internet moderne.&lt;/p>
&lt;p>Les messages LINE que nous envoyons nonchalamment tous les jours, les achats sur Amazon, tout cela danse sur cette belle et simple formule $a^{p-1} \equiv 1 \pmod p$. Le petit théorème de Fermat nous enseigne que peu importe à quel point les mathématiques peuvent être abstraites, le moment viendra toujours où elles seront utiles à l&amp;rsquo;humanité.&lt;/p>
&lt;p>Dans l&amp;rsquo;apprentissage de la programmation et de la théorie cryptographique, comprendre les structures mathématiques à la base de celles-ci sera une arme puissante pour comprendre en profondeur le comportement des bibliothèques fournies sous forme de boîtes noires et pour concevoir des systèmes plus sécurisés.&lt;/p></description></item><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>Le fonctionnement des preuves à divulgation nulle de connaissance (ZKP) et leurs applications récentes dans le Web3 et la sécurité</title><link>http://kenji.blog/fr/p/zero-knowledge-proofs-zkp-web3-security/</link><pubDate>Fri, 11 Sep 2026 19:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/zero-knowledge-proofs-zkp-web3-security/</guid><description>&lt;img src="http://kenji.blog/p/zero-knowledge-proofs-zkp-web3-security/img/eyecatch.jpg" alt="Featured image of post Le fonctionnement des preuves à divulgation nulle de connaissance (ZKP) et leurs applications récentes dans le Web3 et la sécurité" />&lt;h2 id="introduction">Introduction
&lt;/h2>&lt;p>Dans la société numérique moderne, la confidentialité des données et l&amp;rsquo;évolutivité sont devenues deux des enjeux les plus importants. Face aux risques croissants de fuite et d&amp;rsquo;utilisation abusive des informations personnelles, il y a une forte demande pour une technologie qui permette de « prouver que l&amp;rsquo;on possède une information sans la révéler à l&amp;rsquo;autre partie ». C&amp;rsquo;est ce que réalise la &lt;strong>preuve à divulgation nulle de connaissance (Zero-Knowledge Proof : ZKP)&lt;/strong>.&lt;/p>
&lt;p>La preuve à divulgation nulle de connaissance est un concept de théorie cryptographique proposé pour la première fois dans les années 1980 par Shafi Goldwasser, Silvio Micali et Charles Rackoff, mais qui est longtemps resté au stade de la recherche théorique. Cependant, avec l&amp;rsquo;émergence de la technologie blockchain et du Web3, la situation a radicalement changé. Le ZKP est soudainement apparu sur le devant de la scène comme une « baguette magique » permettant de résoudre simultanément les problèmes d&amp;rsquo;évolutivité (limites de capacité de traitement) et de confidentialité (le fait que toutes les transactions soient publiques) auxquels sont confrontées les blockchains publiques comme Ethereum.&lt;/p>
&lt;p>Dans cet article, nous explorerons en détail et en profondeur les concepts fondamentaux des preuves à divulgation nulle, les mécanismes mathématiques et cryptographiques profonds des &lt;strong>zk-SNARKs&lt;/strong> et &lt;strong>zk-STARKs&lt;/strong> actuellement dominants, ainsi que des exemples d&amp;rsquo;applications récentes dans le Web3 et la sécurité, tels que les ZK-Rollups et l&amp;rsquo;identité décentralisée (DID).&lt;/p>
&lt;hr>
&lt;h2 id="quest-ce-que-la-preuve-à-divulgation-nulle-de-connaissance-zkp-">Qu&amp;rsquo;est-ce que la preuve à divulgation nulle de connaissance (ZKP) ?
&lt;/h2>&lt;p>La preuve à divulgation nulle de connaissance (ZKP) désigne un protocole dans lequel un prouveur (Prover) prouve à un vérificateur (Verifier) qu&amp;rsquo;une certaine proposition est vraie, de telle manière qu&amp;rsquo;« aucune information autre que la véracité de cette proposition ne soit transmise ».&lt;/p>
&lt;h3 id="les-3-exigences-que-le-zkp-doit-satisfaire">Les 3 exigences que le ZKP doit satisfaire
&lt;/h3>&lt;p>Pour être considéré comme un ZKP, le protocole doit satisfaire strictement aux trois propriétés suivantes :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Complétude (Completeness)&lt;/strong>
Si la proposition est vraie et que le prouveur et le vérificateur suivent tous deux correctement le protocole, le vérificateur doit accepter la preuve (Accept) avec une probabilité écrasante.&lt;/li>
&lt;li>&lt;strong>Solidité (Soundness)&lt;/strong>
Si la proposition est fausse, même un prouveur malveillant doté d&amp;rsquo;une puissance de calcul extrême ne pourra (sauf probabilité négligeable) tromper le vérificateur pour lui faire accepter la preuve.&lt;/li>
&lt;li>&lt;strong>Divulgation nulle (Zero-Knowledge)&lt;/strong>
Si la proposition est vraie, le vérificateur ne peut obtenir du processus de preuve aucune information autre que le fait que « la proposition est vraie ». Du point de vue du vérificateur, cela est prouvé par la définition mathématique qu&amp;rsquo;il est possible de simuler le processus de preuve (qu&amp;rsquo;il existe un simulateur).&lt;/li>
&lt;/ol>
&lt;h3 id="preuves-interactives-et-preuves-non-interactives">Preuves interactives et preuves non interactives
&lt;/h3>&lt;p>Il existe deux types de ZKP : les &lt;strong>preuves interactives&lt;/strong>, dans lesquelles le prouveur et le vérificateur communiquent plusieurs fois, et les &lt;strong>preuves non interactives&lt;/strong>, dans lesquelles le prouveur envoie les données de la preuve une seule fois pour terminer le processus.&lt;/p>
&lt;h4 id="preuves-interactives-interactive-zkp">Preuves interactives (Interactive ZKP)
&lt;/h4>&lt;p>Les premiers ZKP ont été conçus comme des protocoles interactifs. La célèbre parabole de la « grotte d&amp;rsquo;Ali Baba » en est un exemple. Le déroulement général du protocole est le suivant :&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Prover as "Prover (Prouveur)"
participant Verifier as "Verifier (Vérificateur)"
Note over Prover, Verifier: "Flux de base du protocole de preuve interactive"
Prover->>Verifier: "1. Envoyer l'engagement (Commitment)"
Verifier->>Prover: "2. Envoyer un défi aléatoire (Challenge)"
Prover->>Verifier: "3. Calculer et envoyer la réponse (Response)"
Note over Verifier: "Vérifier la réponse (Verification)"
Verifier-->>Prover: "4. Accepter ou rejeter (Accept / Reject)"
Note over Prover, Verifier: "※ Répéter cela des dizaines de fois pour augmenter la certitude"&lt;/div>
&lt;p>Cette méthode est puissante, mais elle exige que le vérificateur soit en ligne et s&amp;rsquo;avère peu pratique à appliquer à des systèmes distribués asynchrones comme la blockchain. Dans une blockchain, n&amp;rsquo;importe qui doit pouvoir vérifier une preuve passée à tout moment.&lt;/p>
&lt;h4 id="transformation-de-fiat-shamir-fiat-shamir-heuristic-et-non-interactivité">Transformation de Fiat-Shamir (Fiat-Shamir Heuristic) et non-interactivité
&lt;/h4>&lt;p>La &lt;strong>transformation de Fiat-Shamir&lt;/strong> est une méthode révolutionnaire pour convertir une preuve interactive en une preuve non interactive (Non-Interactive Zero-Knowledge Proof : NIZK).&lt;/p>
&lt;p>Au lieu du « défi aléatoire » envoyé par le vérificateur, le prouveur génère lui-même un « défi pseudo-aléatoire » à l&amp;rsquo;aide de son propre engagement et de la valeur de hachage des informations publiques. En supposant qu&amp;rsquo;une fonction de hachage cryptographique (par exemple SHA-256 ou Keccak) agisse comme un oracle aléatoire, le prouveur ne peut ni prédire ni manipuler le défi à l&amp;rsquo;avance, ce qui lui permet de compléter la preuve en envoyant un seul message tout en maintenant une sécurité équivalente à celle d&amp;rsquo;une preuve interactive.&lt;/p>
&lt;hr>
&lt;h2 id="détails-techniques-des-zk-snarks">Détails techniques des zk-SNARKs
&lt;/h2>&lt;p>Actuellement, les &lt;strong>zk-SNARKs&lt;/strong> (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) sont les ZKP les plus largement utilisés. Comme leur nom l&amp;rsquo;indique, ils possèdent la propriété de divulgation nulle (zk), offrent des preuves de très petite taille et rapides à vérifier (Succinct), sont non interactifs (Non-Interactive) et constituent un argument de connaissance (Argument of Knowledge).&lt;/p>
&lt;p>Le fondement des zk-SNARKs repose sur la géométrie algébrique avancée et la théorie cryptographique. Ils convertissent l&amp;rsquo;exécution ou le calcul d&amp;rsquo;un programme en la vérification d&amp;rsquo;une équation polynomiale spécifique.&lt;/p>
&lt;h3 id="1-conversion-en-circuit-arithmétique-et-r1cs-rank-1-constraint-system">1. Conversion en circuit arithmétique et R1CS (Rank-1 Constraint System)
&lt;/h3>&lt;p>Tout d&amp;rsquo;abord, tout calcul que l&amp;rsquo;on souhaite prouver (un algorithme ou la logique d&amp;rsquo;un contrat intelligent) est converti en un &lt;strong>circuit arithmétique (Arithmetic Circuit)&lt;/strong> composé de portes d&amp;rsquo;addition et de multiplication.&lt;/p>
&lt;p>Ensuite, ce circuit arithmétique est converti en un ensemble d&amp;rsquo;équations matricielles appelé &lt;strong>R1CS (Rank-1 Constraint System)&lt;/strong>. Le R1CS est le problème de trouver, pour un vecteur de variables $x$, des matrices $A, B, C$ qui satisfont la contrainte suivante :&lt;/p>
$$ (A \cdot x) \circ (B \cdot x) = C \cdot x $$
&lt;p>Où $\circ$ représente le produit de Hadamard (produit élément par élément). Cette contrainte garantit que toutes les portes logiques (en particulier les portes de multiplication) du circuit sont calculées correctement.&lt;/p>
&lt;h3 id="2-conversion-en-qap-quadratic-arithmetic-program">2. Conversion en QAP (Quadratic Arithmetic Program)
&lt;/h3>&lt;p>Puisqu&amp;rsquo;il existe un nombre infini de contraintes matricielles R1CS, il serait très inefficace de les vérifier individuellement. Par conséquent, à l&amp;rsquo;aide de l&amp;rsquo;interpolation de Lagrange, ces contraintes sont compressées en une seule équation polynomiale. C&amp;rsquo;est ce qu&amp;rsquo;on appelle le &lt;strong>QAP (Quadratic Arithmetic Program)&lt;/strong>.&lt;/p>
&lt;p>Par la conversion en QAP, le problème à prouver se réduit à la question : « Un polynôme spécifique $P(x)$ est-il divisible par un autre polynôme connu $Z(x)$ ? ».&lt;/p>
$$ P(x) = L(x) \cdot R(x) - O(x) $$
&lt;p>Ici, $L(x), R(x), O(x)$ sont des combinaisons des polynômes correspondant respectivement à chaque ligne des matrices $A, B, C$. Si le prouveur connaît la bonne solution (Witness), la valeur de $P(x)$ sera de 0 à chaque racine (point d&amp;rsquo;évaluation), ce qui signifie que $P(x)$ aura le polynôme cible $Z(x)$ comme facteur. En d&amp;rsquo;autres termes, il existe un polynôme $H(x)$ tel que l&amp;rsquo;équation suivante soit satisfaite :&lt;/p>
$$ P(x) = H(x) \cdot Z(x) $$
&lt;p>Le vérificateur peut vérifier instantanément que l&amp;rsquo;ensemble du calcul a été effectué correctement en vérifiant simplement si cette équation $P(s) = H(s) \cdot Z(s)$ tient pour un point secret aléatoire $s$. C&amp;rsquo;est le secret de la « concision (Succinct) ».&lt;/p>
&lt;h3 id="3-cryptographie-sur-les-courbes-elliptiques-et-couplages-bilinear-pairings">3. Cryptographie sur les courbes elliptiques et couplages (Bilinear Pairings)
&lt;/h3>&lt;p>Cependant, si le vérificateur connaît le point secret $s$, il devient possible pour le prouveur de forger de faux polynômes pour satisfaire l&amp;rsquo;équation (effondrement de la solidité). Par conséquent, il est nécessaire d&amp;rsquo;effectuer le calcul tout en gardant $s$ chiffré (en utilisant le chiffrement homomorphe) afin que personne ne le connaisse.&lt;/p>
&lt;p>Ceci est réalisé grâce aux &lt;strong>couplages sur courbes elliptiques (Bilinear Pairings)&lt;/strong>.
Le couplage $e$ est une fonction spéciale qui permet, à partir de deux valeurs chiffrées, de calculer une valeur équivalente au chiffrement de leur produit.&lt;/p>
$$ e(g_1^a, g_2^b) = e(g_1, g_2)^{ab} $$
&lt;p>Le prouveur, sans connaître $s$ lui-même, calcule les valeurs chiffrées des polynômes $P(s)$ et $H(s)$ en utilisant des valeurs chiffrées des puissances de $s$ (appelées CRS : Common Reference String). Le vérificateur utilise la fonction de couplage pour vérifier si la relation $P(s) = H(s) \cdot Z(s)$ tient, tout en conservant les valeurs sous forme chiffrée.&lt;/p>
&lt;h3 id="4-configuration-de-confiance-trusted-setup">4. Configuration de confiance (Trusted Setup)
&lt;/h3>&lt;p>La plus grande faiblesse des zk-SNARKs (en particulier des premiers comme Groth16) est la nécessité d&amp;rsquo;un processus pour générer le point secret $s$, appelé &lt;strong>configuration de confiance (Trusted Setup)&lt;/strong>. Si le générateur de $s$ conservait sa valeur au lieu de la détruire, il pourrait générer n&amp;rsquo;importe quelle fausse preuve (problème des déchets toxiques ou Toxic Waste).&lt;/p>
&lt;p>Pour éviter cela, on organise une cérémonie appelée « Ceremony » utilisant le calcul multiparti (MPC - Multi-Party Computation). De nombreux participants collaborent pour fournir de l&amp;rsquo;aléatoire, et tant qu&amp;rsquo;au moins un participant détruit honnêtement sa propre valeur aléatoire, la sécurité de l&amp;rsquo;ensemble du système est préservée. Cependant, la recherche pour éliminer cette dépendance se poursuit depuis des années.&lt;/p>
&lt;hr>
&lt;h2 id="détails-techniques-des-zk-starks">Détails techniques des zk-STARKs
&lt;/h2>&lt;p>Les &lt;strong>zk-STARKs&lt;/strong> (Zero-Knowledge Scalable Transparent Argument of Knowledge) sont apparus comme une réponse à la dépendance à la configuration de confiance et au risque que la cryptographie sur courbes elliptiques soit brisée par les ordinateurs quantiques.&lt;/p>
&lt;p>Développés par Eli Ben-Sasson et d&amp;rsquo;autres, les STARKs se caractérisent, comme leur nom « Transparent » l&amp;rsquo;indique, par le fait qu&amp;rsquo;ils ne nécessitent aucune configuration de confiance, et comme « Scalable » (évolutif) l&amp;rsquo;indique, par le fait que la taille de la preuve et le temps de vérification restent efficaces même lorsque la complexité du calcul augmente.&lt;/p>
&lt;h3 id="1-engagements-polynomiaux-et-protocole-fri">1. Engagements polynomiaux et protocole FRI
&lt;/h3>&lt;p>Les zk-STARKs fondent leur sécurité &lt;strong>uniquement sur des fonctions de hachage&lt;/strong>, et non sur la cryptographie des courbes elliptiques. Par conséquent, ils possèdent les propriétés d&amp;rsquo;une cryptographie post-quantique (Post-Quantum Cryptography).&lt;/p>
&lt;p>La vérification du calcul est effectuée en utilisant les propriétés de polynômes unidimensionnels ou multidimensionnels, après que le calcul ait été converti dans un format appelé AIR (Algebraic Intermediate Representation). Le cœur des STARKs réside dans le protocole &lt;strong>FRI (Fast Reed-Solomon Interactive Oracle Proof of Proximity)&lt;/strong>.&lt;/p>
&lt;p>Le protocole FRI est une technique permettant de vérifier « si une certaine fonction est suffisamment proche d&amp;rsquo;un polynôme d&amp;rsquo;un degré spécifique (Proximity) ». Le prouveur s&amp;rsquo;engage sur les valeurs du polynôme en tant que feuilles d&amp;rsquo;un arbre de Merkle (Merkle Tree) (engagement polynomial).&lt;/p>
&lt;div class="mermaid">graph TD
Root["Racine de Merkle (Engagement)"] --> Node0["Nœud 0"]
Root --> Node1["Nœud 1"]
Node0 --> Leaf0["P(x_0)"]
Node0 --> Leaf1["P(x_1)"]
Node1 --> Leaf2["P(x_2)"]
Node1 --> Leaf3["P(x_3)"]&lt;/div>
&lt;p>Le vérificateur demande la révélation de quelques points aléatoires et utilise des preuves de Merkle pour confirmer qu&amp;rsquo;ils sont inclus dans l&amp;rsquo;engagement. En répétant cela récursivement, il est garanti avec une probabilité écrasante que le degré du polynôme d&amp;rsquo;origine est effectivement faible.&lt;/p>
&lt;h3 id="comparaison-entre-zk-snarks-et-zk-starks">Comparaison entre zk-SNARKs et zk-STARKs
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Caractéristique&lt;/th>
&lt;th style="text-align:left">zk-SNARKs&lt;/th>
&lt;th style="text-align:left">zk-STARKs&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Hypothèse cryptographique&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Courbes elliptiques, couplages&lt;/td>
&lt;td style="text-align:left">Fonctions de hachage résistantes aux collisions&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Configuration de confiance&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Requise (Plonk etc. sont universels)&lt;/td>
&lt;td style="text-align:left">Non requise (Transparent)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Résistance quantique&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Non&lt;/td>
&lt;td style="text-align:left">Oui&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Taille de la preuve&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Très petite (~200 octets)&lt;/td>
&lt;td style="text-align:left">Assez grande (des dizaines de Ko)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Coût de calcul de la génération de preuve&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Élevé&lt;/td>
&lt;td style="text-align:left">Relativement plus faible que les SNARKs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Coût de vérification (Frais de gaz)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Très faible (constant)&lt;/td>
&lt;td style="text-align:left">Faible (augmente de manière logarithmique)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Ces dernières années, des « SNARKs ne nécessitant pas de configuration de confiance, ou nécessitant une seule configuration » tels que Plonk ou Halo2 sont apparus, et la frontière entre les SNARKs et les STARKs devient progressivement floue, mais la différence fondamentale dans l&amp;rsquo;approche mathématique reste importante.&lt;/p>
&lt;hr>
&lt;h2 id="applications-récentes-des-preuves-à-divulgation-nulle-dans-le-web3-et-la-sécurité">Applications récentes des preuves à divulgation nulle dans le Web3 et la sécurité
&lt;/h2>&lt;p>Passé de la théorie à la pratique, le ZKP révolutionne actuellement le Web3 et la cybersécurité.&lt;/p>
&lt;h3 id="1-la-mise-à-léchelle-ultime-dethereum-par-les-zk-rollups">1. La mise à l&amp;rsquo;échelle ultime d&amp;rsquo;Ethereum par les ZK-Rollups
&lt;/h3>&lt;p>Les blockchains de couche 1 (L1) comme Ethereum sont confrontées à des contraintes importantes en matière d&amp;rsquo;évolutivité (le trilemme), car elles privilégient la décentralisation et la sécurité. La solution de couche 2 (L2) définitive à ce problème est constituée par les &lt;strong>ZK-Rollups&lt;/strong>.&lt;/p>
&lt;p>Dans un ZK-Rollup, des milliers de transactions sont exécutées et traitées hors chaîne (L2), et un « seul ZKP (Proof of Validity) » est généré pour montrer qu&amp;rsquo;elles ont toutes été exécutées correctement. Le contrat intelligent sur la chaîne L1 n&amp;rsquo;a plus qu&amp;rsquo;à vérifier cette preuve.&lt;/p>
&lt;div class="mermaid">flowchart LR
Users["Utilisateurs (Envoi Tx)"] --> Sequencer["Séquenceur (Collecte/Exécution Tx)"]
Sequencer --> Prover["Prouveur (Génération ZKP)"]
Sequencer --> L1Contract["Contrat intelligent L1 (Publication données Tx)"]
Prover --> L1Contract["Soumission ZKP (Preuve)"]
L1Contract --> Verify["Vérification et mise à jour de l'état"]&lt;/div>
&lt;p>Le plus grand avantage des ZK-Rollups, contrairement aux Optimistic Rollups (comme Arbitrum ou Optimism), est qu&amp;rsquo;aucune période de contestation (généralement 7 jours) n&amp;rsquo;est requise pour les preuves de fraude (Fraud Proofs). Puisque l&amp;rsquo;exactitude est garantie de manière cryptographique, le retrait des fonds (Finalité) vers la L1 est complété dès que la preuve est vérifiée. Actuellement, des projets comme zkSync, Starknet, Scroll ou Polygon zkEVM se livrent une concurrence acharnée, et la réalisation de &lt;strong>zkEVM&lt;/strong> compatibles avec l&amp;rsquo;EVM (Ethereum Virtual Machine) stimule une croissance rapide de l&amp;rsquo;écosystème.&lt;/p>
&lt;h3 id="2-identité-préservant-la-confidentialité-zkp-for-identity">2. Identité préservant la confidentialité (ZKP for Identity)
&lt;/h3>&lt;p>L&amp;rsquo;authentification personnelle dans le monde numérique est également fondamentalement transformée par le ZKP.
Par exemple, pour répondre à la question « Avez-vous plus de 18 ans ? », les systèmes traditionnels exigent de présenter un permis de conduire ou un passeport, ce qui transmet également des informations personnelles inutiles telles que le nom et l&amp;rsquo;adresse.&lt;/p>
&lt;p>Avec le ZKP, sur la base d&amp;rsquo;un certificat numérique émis par un organisme public (Verifiable Credential), il devient possible de &lt;strong>prouver mathématiquement uniquement le fait&lt;/strong> que « d&amp;rsquo;après ma date de naissance, j&amp;rsquo;ai plus de 18 ans à la date d&amp;rsquo;aujourd&amp;rsquo;hui ». Le vérificateur n&amp;rsquo;a besoin que de vérifier la signature du certificat et le ZKP, et ne peut pas connaître la date de naissance ni l&amp;rsquo;identité de l&amp;rsquo;utilisateur.&lt;/p>
&lt;p>Même dans les projets de preuve d&amp;rsquo;humanité (Proof of Personhood) comme Worldcoin, au lieu de stocker et de partager directement les données de l&amp;rsquo;iris, un mécanisme employant le ZKP est utilisé pour prouver uniquement « qu&amp;rsquo;il s&amp;rsquo;agit d&amp;rsquo;un être humain unique ».&lt;/p>
&lt;h3 id="3-contrats-intelligents-confidentiels-et-utilisation-en-entreprise">3. Contrats intelligents confidentiels et utilisation en entreprise
&lt;/h3>&lt;p>La nature publique des blockchains (« toutes les données sont publiques ») constituait un obstacle majeur pour les entreprises souhaitant traiter des transactions confidentielles et des informations sur les chaînes d&amp;rsquo;approvisionnement sur la blockchain.&lt;/p>
&lt;p>En utilisant la technologie ZKP (par exemple des réseaux axés sur la confidentialité comme Aleo et Aztec), il est possible de graver uniquement la validité des mises à jour de l&amp;rsquo;état sur la chaîne publique, tout en gardant les valeurs d&amp;rsquo;entrée et de sortie des transactions, voire la logique même du contrat intelligent exécuté, sous forme chiffrée. Cela empêche le front-running (MEV) dans la finance décentralisée (DeFi) et permet la construction de réseaux de consortiums confidentiels entre entreprises, tout en bénéficiant de la haute sécurité de la chaîne publique.&lt;/p>
&lt;hr>
&lt;h2 id="défis-futurs-et-perspectives-du-zkp">Défis futurs et perspectives du ZKP
&lt;/h2>&lt;p>Le ZKP est indéniablement une technologie fondamentale de la prochaine génération, mais il reste quelques défis.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Coût de calcul de la génération de preuve et accélération matérielle&lt;/strong>
La génération de ZKP nécessite des opérations polynomiales massives, des FFT (transformées de Fourier rapides) et des MSM (multiplications multi-scalaires). Actuellement, la recherche avance rapidement sur le développement de matériel dédié (FPGA ou ASIC) pour accélérer cette génération de preuves, ce que l&amp;rsquo;on appelle le &lt;strong>minage ZKP&lt;/strong> (Réseau de Prouveurs).&lt;/li>
&lt;li>&lt;strong>Standardisation et amélioration de l&amp;rsquo;expérience développeur (DX)&lt;/strong>
Des langages dédiés pour écrire des circuits ZKP tels que Circom, Cairo, Noir et Leo se multiplient. Des normes unifiées pour les rassembler et la maturation de compilateurs capables de générer automatiquement des circuits ZKP à partir de Rust ou C++ existants seront la clé pour l&amp;rsquo;adoption du ZKP par les ingénieurs logiciels en général.&lt;/li>
&lt;/ol>
&lt;h2 id="conclusion">Conclusion
&lt;/h2>&lt;p>La preuve à divulgation nulle de connaissance (ZKP) a évolué d&amp;rsquo;une simple « technologie pour accroître l&amp;rsquo;anonymat des cryptomonnaies » vers une « technologie à usage général qui redéfinit la confiance (Trust) sur l&amp;rsquo;ensemble d&amp;rsquo;Internet ». Les petites preuves calculées dans les profondeurs des équations et de la théorie cryptographique élargissent infiniment l&amp;rsquo;évolutivité de la blockchain et agissent comme un bouclier robuste pour protéger notre vie privée.&lt;/p>
&lt;p>Vers la véritable adoption massive du Web3 et la construction d&amp;rsquo;un Internet de nouvelle génération sécurisé et privé, la preuve à divulgation nulle de connaissance continuera de fonctionner comme la pièce la plus vitale. Il faudra garder un œil sur l&amp;rsquo;évolution future de la technologie ZKP.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Références et liens connexes&lt;/em>&lt;/p>
&lt;ul>
&lt;li>Groth, J. (2016). &amp;ldquo;On the Size of Pairing-based Non-interactive Arguments&amp;rdquo;&lt;/li>
&lt;li>Ben-Sasson, E., et al. (2018). &amp;ldquo;Scalable, transparent, and post-quantum secure computational integrity&amp;rdquo;&lt;/li>
&lt;li>Blog de Vitalik Buterin sur les zk-SNARKs et zk-STARKs&lt;/li>
&lt;/ul></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>Qu'est-ce que le chiffrement homomorphe complet (FHE) ? Explication de la clé de la sécurité de nouvelle génération</title><link>http://kenji.blog/fr/p/fully-homomorphic-encryption-fhe-explained/</link><pubDate>Fri, 11 Sep 2026 11:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/fully-homomorphic-encryption-fhe-explained/</guid><description>&lt;img src="http://kenji.blog/p/fully-homomorphic-encryption-fhe-explained/img/eyecatch.jpg" alt="Featured image of post Qu'est-ce que le chiffrement homomorphe complet (FHE) ? Explication de la clé de la sécurité de nouvelle génération" />&lt;p>Alors que le cloud computing et les technologies d&amp;rsquo;IA s&amp;rsquo;imposent comme les fondations de notre société, le compromis entre la « confidentialité des données » et l&amp;rsquo;« utilisation des données » est devenu l&amp;rsquo;un des défis les plus importants. Bien qu&amp;rsquo;il y ait une demande croissante pour que les IA analysent des données hautement confidentielles dans le cloud, telles que des données médicales, des informations financières ou des données biométriques personnelles, de nombreuses entreprises hésitent à envoyer leurs données à l&amp;rsquo;extérieur en raison de préoccupations liées à la sécurité.&lt;/p>
&lt;p>Les technologies de chiffrement traditionnelles (telles qu&amp;rsquo;AES et RSA) excellent à protéger les données stockées (Data at Rest) et les données en transit sur le réseau (Data in Transit). Cependant, &lt;strong>lorsque le serveur effectue des traitements (calculs)&lt;/strong> sur les données, comme des recherches ou de l&amp;rsquo;apprentissage automatique (Data in Use), &lt;strong>il est nécessaire de déchiffrer au préalable les données pour les ramener en texte clair&lt;/strong>. Si le serveur est piraté au moment du déchiffrement, ou si un administrateur interne malveillant jette un coup d&amp;rsquo;œil aux données, cela conduit directement à une fuite d&amp;rsquo;informations.&lt;/p>
&lt;p>La technologie de rêve qui surmonte cette faiblesse fondamentale du « déchiffrement lors du traitement » est le &lt;strong>Chiffrement Homomorphe Complet (Fully Homomorphic Encryption : FHE)&lt;/strong>. L&amp;rsquo;utilisation du FHE permet d&amp;rsquo;effectuer des calculs sur les données tout en les gardant chiffrées, sans jamais les déchiffrer, et de renvoyer uniquement le texte chiffré du résultat au client.&lt;/p>
&lt;p>Dans cet article, nous expliquerons en profondeur le FHE, clé de la sécurité de nouvelle génération, de son concept à son histoire, en passant par la percée révolutionnaire de Craig Gentry, ses bases mathématiques (comme le Ring-LWE), son plus grand défi qu&amp;rsquo;est le « bruit » et sa solution (le bootstrapping), jusqu&amp;rsquo;aux dernières bibliothèques d&amp;rsquo;implémentation.&lt;/p>
&lt;hr>
&lt;h2 id="1-quest-ce-que-le-chiffrement-homomorphe--concepts-de-base">1. Qu&amp;rsquo;est-ce que le chiffrement homomorphe ? Concepts de base
&lt;/h2>&lt;p>« Homomorphe » est un terme d&amp;rsquo;algèbre qui désigne la propriété de pouvoir mapper des ensembles ayant une certaine structure tout en préservant la structure de leurs opérations. Dans la théorie de la cryptographie, l&amp;rsquo;« homomorphisme » est la propriété selon laquelle &lt;strong>les opérations dans l&amp;rsquo;espace du texte clair correspondent aux opérations dans l&amp;rsquo;espace du texte chiffré&lt;/strong>.&lt;/p>
&lt;p>Exprimé par une formule mathématique simple, soit $E(\cdot)$ la fonction de chiffrement et $D(\cdot)$ la fonction de déchiffrement pour les textes clairs $m_1$ et $m_2$. Si $\circ$ est une opération (comme l&amp;rsquo;addition ou la multiplication) sur les textes clairs, et $\diamond$ une opération sur les textes chiffrés, la relation suivante est établie :&lt;/p>
$$ D(E(m_1) \diamond E(m_2)) = m_1 \circ m_2 $$
&lt;p>En d&amp;rsquo;autres termes, déchiffrer le résultat de l&amp;rsquo;application d&amp;rsquo;une certaine opération $\diamond$ sur les textes chiffrés $E(m_1)$ et $E(m_2)$ donnera exactement le même résultat que l&amp;rsquo;opération $\circ$ appliquée sur les textes clairs d&amp;rsquo;origine.&lt;/p>
&lt;h3 id="flux-de-données-dans-le-cloud-computing">Flux de données dans le cloud computing
&lt;/h3>&lt;p>L&amp;rsquo;architecture de traitement dans le cloud utilisant le FHE est complètement différente des architectures traditionnelles. Le diagramme ci-dessous illustre le flux de traitement de données sécurisé tirant parti du FHE.&lt;/p>
&lt;div class="mermaid">graph TD
A["Client (Détient la clé privée)"] -->|1. Chiffre le texte clair x : E(x)| B["Serveur Cloud (Uniquement données chiffrées)"]
B -->|2. Applique la fonction f en gardant le chiffrement : E(f(x))| B
B -->|3. Texte chiffré du résultat du calcul E(y)| A
A -->|4. Déchiffre avec la clé privée : y = f(x)| A
style A fill:#d4edda,stroke:#28a745
style B fill:#f8d7da,stroke:#dc3545&lt;/div>
&lt;p>Le serveur reçoit les données chiffrées $E(x)$, mais ne possédant pas la clé privée, il lui est absolument impossible d&amp;rsquo;en connaître le contenu. Cependant, en utilisant les propriétés du FHE, il peut appliquer une fonction $f$ (par exemple, un modèle d&amp;rsquo;inférence d&amp;rsquo;apprentissage automatique) au texte chiffré pour générer $E(f(x))$. Le client le reçoit et le déchiffre avec sa propre clé privée, obtenant ainsi le résultat souhaité $y = f(x)$.&lt;/p>
&lt;hr>
&lt;h2 id="2-lhistoire-de-lévolution-du-chiffrement-homomorphe--phe-she-fhe">2. L&amp;rsquo;histoire de l&amp;rsquo;évolution du chiffrement homomorphe : PHE, SHE, FHE
&lt;/h2>&lt;p>Le chiffrement homomorphe n&amp;rsquo;a pas atteint sa forme « complète » actuelle en une seule fois. Il est largement classé en trois étapes selon le type et le nombre d&amp;rsquo;opérations réalisables.&lt;/p>
&lt;h3 id="chiffrement-partiellement-homomorphe-phe--partially-homomorphic-encryption">Chiffrement Partiellement Homomorphe (PHE : Partially Homomorphic Encryption)
&lt;/h3>&lt;p>Le PHE est un schéma de chiffrement permettant d&amp;rsquo;effectuer &lt;strong>soit des additions, soit des multiplications&lt;/strong>, de manière illimitée. En réalité, des chiffrements possédant cette propriété existent depuis longtemps.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Chiffrement RSA (homomorphisme vis-à-vis de la multiplication)&lt;/strong>
Le chiffrement RSA possède involontairement un homomorphisme multiplicatif. Soit les textes clairs $m_1, m_2$ et la clé publique $(e, N)$ :
$$ E(m_1) = m_1^e \pmod N $$
$$ E(m_2) = m_2^e \pmod N $$
En les multipliant :
$$ E(m_1) \times E(m_2) = (m_1 \cdot m_2)^e \pmod N = E(m_1 \times m_2) $$
Ainsi, la multiplication des textes chiffrés correspond à la multiplication des textes clairs.&lt;/li>
&lt;li>&lt;strong>Chiffrement de Paillier (homomorphisme vis-à-vis de l&amp;rsquo;addition)&lt;/strong>
Inventé en 1999, le chiffrement de Paillier possède un homomorphisme pour l&amp;rsquo;addition. Il est utilisé de manière pratique dans des applications telles que le vote électronique (où les votes chiffrés sont comptés, et seul le résultat final est déchiffré).&lt;/li>
&lt;/ul>
&lt;h3 id="chiffrement-quelque-peu-homomorphe-she--somewhat-homomorphic-encryption">Chiffrement Quelque Peu Homomorphe (SHE : Somewhat Homomorphic Encryption)
&lt;/h3>&lt;p>C&amp;rsquo;est une méthode permettant d&amp;rsquo;exécuter &lt;strong>à la fois&lt;/strong> des additions et des multiplications, mais avec &lt;strong>une limite sur le nombre d&amp;rsquo;opérations (la profondeur du circuit)&lt;/strong>. En raison de l&amp;rsquo;accumulation du « bruit » (expliqué plus tard), effectuer plus d&amp;rsquo;un certain nombre de multiplications rend le déchiffrement impossible. Le chiffrement BGN (Boneh-Goh-Nissim) de 2005 en est un exemple, mais il a ses limites pour effectuer des calculs pratiques complexes (comme le deep learning).&lt;/p>
&lt;h3 id="chiffrement-homomorphe-complet-fhe--fully-homomorphic-encryption">Chiffrement Homomorphe Complet (FHE : Fully Homomorphic Encryption)
&lt;/h3>&lt;p>Il s&amp;rsquo;agit d&amp;rsquo;un schéma de chiffrement permettant d&amp;rsquo;effectuer à la fois l&amp;rsquo;addition et la multiplication &lt;strong>un nombre illimité de fois&lt;/strong>. Semblable à la complétude de Turing en théorie de l&amp;rsquo;information, pouvoir combiner infiniment des additions (équivalentes au XOR) et des multiplications (équivalentes au AND) signifie qu&amp;rsquo;en principe, n&amp;rsquo;importe quelle fonction ou algorithme calculable peut être exécuté tout en restant chiffré.&lt;/p>
&lt;p>Le FHE a longtemps été considéré comme le « Saint Graal de la cryptographie », et certains disaient même qu&amp;rsquo;il pourrait être irréalisable. Cependant, en 2009, &lt;strong>Craig Gentry&lt;/strong>, alors étudiant en doctorat à l&amp;rsquo;Université de Stanford, a proposé le premier schéma FHE utilisant les réseaux idéaux (Ideal Lattices), bouleversant ainsi le monde.&lt;/p>
&lt;hr>
&lt;h2 id="3-les-bases-mathématiques-du-fhe--le-problème-lwe-et-ring-lwe">3. Les bases mathématiques du FHE : le problème LWE et Ring-LWE
&lt;/h2>&lt;p>La plupart des schémas FHE actuellement dominants sont basés sur le &lt;strong>problème LWE (Learning With Errors)&lt;/strong>, un défi mathématique de la « cryptographie fondée sur les réseaux (Lattice-based Cryptography) », également connue sous le nom de cryptographie post-quantique.&lt;/p>
&lt;h3 id="compréhension-intuitive-du-problème-lwe">Compréhension intuitive du problème LWE
&lt;/h3>&lt;p>Résoudre un système d&amp;rsquo;équations linéaires est facile en utilisant l&amp;rsquo;élimination de Gauss ou des méthodes similaires.&lt;/p>
$$ \begin{cases} 3s_1 + 4s_2 + 2s_3 \equiv 12 \pmod{17} \\ 1s_1 + 9s_2 + 5s_3 \equiv 8 \pmod{17} \\ \vdots \end{cases} $$
&lt;p>Mais que se passe-t-il si l&amp;rsquo;on ajoute une très petite « erreur (bruit) aléatoire » $e$ au résultat de ces équations ?&lt;/p>
$$ \begin{cases} 3s_1 + 4s_2 + 2s_3 + e_1 \equiv 13 \pmod{17} \\ 1s_1 + 9s_2 + 5s_3 + e_2 \equiv 7 \pmod{17} \\ \vdots \end{cases} $$
&lt;p>Le simple ajout de cette erreur $e$ transforme le problème de la découverte du vecteur de variables secrètes $\vec{s}$ en un problème NP-difficile, complexe à déchiffrer même en utilisant les supercalculateurs actuels ou les ordinateurs quantiques. C&amp;rsquo;est le problème LWE.&lt;/p>
&lt;h3 id="le-problème-ring-lwe-rlwe">Le problème Ring-LWE (RLWE)
&lt;/h3>&lt;p>Comme le problème LWE standard implique des opérations matricielles, la taille des clés est extrêmement importante (atteignant parfois des gigaoctets) et l&amp;rsquo;efficacité des calculs est faible. Pour résoudre ce problème, le &lt;strong>problème Ring-LWE (RLWE)&lt;/strong> utilisant des opérations sur des anneaux de polynômes a été introduit.&lt;/p>
&lt;p>Dans le RLWE, les éléments appartiennent à l&amp;rsquo;anneau polynomial $R_q = \mathbb{Z}_q[x] / (x^N + 1)$ (où $N$ est une puissance de 2 et $q$ est un nombre premier servant de modulo).
Soit $s(x)$ le polynôme représentant la clé privée, $a(x)$ un polynôme aléatoire et $e(x)$ un petit polynôme de bruit, la clé publique sera la paire suivante :&lt;/p>
$$ (a(x), b(x)) \quad \text{where} \quad b(x) = -a(x) \cdot s(x) + e(x) \pmod q $$
&lt;p>Lors du chiffrement, on utilise les propriétés de ces polynômes pour encoder le texte clair $m(x)$ et générer le texte chiffré.&lt;/p>
&lt;hr>
&lt;h2 id="4-le-plus-grand-obstacle--le--bruit--et-le-bootstrapping-de-gentry">4. Le plus grand obstacle : le « bruit » et le Bootstrapping de Gentry
&lt;/h2>&lt;p>Le concept le plus important pour comprendre le FHE est la &lt;strong>« gestion du bruit »&lt;/strong>.&lt;/p>
&lt;p>Dans les chiffrements basés sur LWE/RLWE, on introduit intentionnellement un petit « bruit (erreur) » pour garantir la sécurité.
En termes généraux, le processus de déchiffrement d&amp;rsquo;un texte chiffré $c$ d&amp;rsquo;un texte clair $m$ peut être exprimé par l&amp;rsquo;équation suivante :&lt;/p>
$$ D(c) = (c \cdot s) \pmod q = m + \text{noise} $$
&lt;p>Lors du déchiffrement, le texte clair correct $m$ est obtenu en éliminant ce &lt;code>noise&lt;/code> par un processus tel que l&amp;rsquo;arrondi. Cependant, effectuer des opérations homomorphes (en particulier la multiplication) entre des textes chiffrés amplifie considérablement ce bruit.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Addition homomorphe&lt;/strong> : Le bruit augmente de manière additive ($e_1 + e_2$). C&amp;rsquo;est une augmentation relativement modérée.&lt;/li>
&lt;li>&lt;strong>Représentation mathématique de l&amp;rsquo;homomorphisme par addition homomorphe&lt;/strong> :
$$ E(m_1) \oplus E(m_2) = E(m_1 + m_2) $$&lt;/li>
&lt;li>&lt;strong>Multiplication homomorphe&lt;/strong> : Le bruit explose de manière multiplicative (car il implique des termes comme $e_1 \times e_2$). Après seulement quelques multiplications, le bruit dépasse le seuil $q/2$, ce qui rend l&amp;rsquo;arrondi correct impossible et entraîne un échec de déchiffrement.&lt;/li>
&lt;li>&lt;strong>Représentation mathématique de l&amp;rsquo;homomorphisme par multiplication homomorphe&lt;/strong> :
$$ E(m_1) \otimes E(m_2) = E(m_1 \times m_2) $$&lt;/li>
&lt;/ul>
&lt;p>C&amp;rsquo;est la raison pour laquelle le FHE est resté longtemps irréalisable, se limitant au SHE (avec un nombre d&amp;rsquo;opérations restreint).&lt;/p>
&lt;h3 id="la-magie-du-bootstrapping">La magie du Bootstrapping
&lt;/h3>&lt;p>La contribution géniale de Craig Gentry a été d&amp;rsquo;inventer une méthode de réduction de bruit appelée &lt;strong>« bootstrapping »&lt;/strong>. Ce fut un changement de paradigme en cryptographie.&lt;/p>
&lt;p>Intuitivement, il s&amp;rsquo;agit d&amp;rsquo;une opération où l&amp;rsquo;« on &amp;lsquo;déchiffre&amp;rsquo; le texte chiffré tout en le gardant à l&amp;rsquo;état chiffré pour le nettoyer et le placer dans un nouveau texte chiffré avant qu&amp;rsquo;il ne soit submergé de bruit et ne se corrompe ».&lt;/p>
&lt;ol>
&lt;li>Supposons qu&amp;rsquo;il y ait un texte chiffré avec un bruit élevé, $C_{noisy}$.&lt;/li>
&lt;li>Le client remet au préalable au serveur sa clé privée $sk$ « chiffrée avec la clé publique » $E_{pk}(sk)$ (appelée clé de bootstrapping).&lt;/li>
&lt;li>Le serveur exécute homomorphiquement un &lt;strong>circuit de déchiffrement (Decryption Circuit)&lt;/strong> sur $C_{noisy}$.&lt;/li>
&lt;li>Concrètement, il effectue un « déchiffrement dans l&amp;rsquo;espace chiffré » sur $E_{pk}(C_{noisy})$ en utilisant $E_{pk}(sk)$.&lt;/li>
&lt;li>Bien que ce circuit de déchiffrement lui-même soit une opération homomorphe et génère donc un nouveau bruit, le bruit du nouveau texte chiffré produit, $C_{fresh}$, est réinitialisé à un « niveau fixe » constant.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["Texte chiffré à haut bruit C_noisy"] --> B["Circuit de déchiffrement homomorphe (Eval_Dec)"]
C["Clé privée chiffrée E(sk)"] --> B
B --> D["Texte chiffré à faible bruit C_fresh"]
style B fill:#ffeeba,stroke:#ffc107&lt;/div>
&lt;p>En exécutant périodiquement ce bootstrapping au cours des calculs, il est théoriquement devenu possible de calculer des circuits d&amp;rsquo;une profondeur infinie (réalisant ainsi le FHE). Cependant, dans le schéma initial de Gentry, le coût de calcul du processus de bootstrapping était désespérément élevé, prenant de quelques dizaines de minutes à plusieurs heures pour chaque exécution.&lt;/p>
&lt;hr>
&lt;h2 id="5-générations-de-fhe-et-évolution-des-principaux-schémas">5. Générations de FHE et évolution des principaux schémas
&lt;/h2>&lt;p>Afin de rendre le FHE pratique, les cryptographes du monde entier ont rivalisé pour améliorer les algorithmes. Actuellement, le FHE est principalement classé en quatre générations ou familles.&lt;/p>
&lt;h3 id="2ème-génération--opérations-exactes-sur-les-entiers-bgv-bfv">2ème Génération : Opérations exactes sur les entiers (BGV, BFV)
&lt;/h3>&lt;p>Apparus entre 2011 et 2012, il s&amp;rsquo;agit des schémas &lt;strong>BGV (Brakerski-Gentry-Vaikuntanathan)&lt;/strong> et &lt;strong>BFV (Brakerski/Fan-Vercauteren)&lt;/strong>. Ils sont basés sur le RLWE et sont adaptés à l&amp;rsquo;arithmétique modulaire sur les nombres entiers (calculs exacts).
Leur particularité est de supporter des techniques de traitement par lots (Batching) telles que SIMD (Single Instruction, Multiple Data), ce qui permet de regrouper des milliers d&amp;rsquo;emplacements de données dans un seul énorme texte chiffré polynomial pour effectuer des calculs parallèles en une seule fois.&lt;/p>
&lt;h3 id="3ème-génération--accélération-du-bootstrapping-gsw-fhew-tfhe">3ème Génération : Accélération du Bootstrapping (GSW, FHEW, TFHE)
&lt;/h3>&lt;p>Le schéma &lt;strong>GSW (Gentry-Sahai-Waters)&lt;/strong> de 2013 a simplifié la structure du FHE. Et son développement a conduit au &lt;strong>TFHE (Fast Fully Homomorphic Encryption over the Torus)&lt;/strong>, qui est l&amp;rsquo;un des schémas dominants aujourd&amp;rsquo;hui.
La caractéristique du TFHE est que son bootstrapping est extrêmement rapide (de l&amp;rsquo;ordre de la milliseconde). Il excelle dans les opérations au niveau des portes (circuits logiques tels que AND, XOR), et la taille de son texte chiffré étant relativement petite, il est adapté à l&amp;rsquo;évaluation rapide de n&amp;rsquo;importe quel circuit logique.&lt;/p>
&lt;h3 id="4ème-génération--spécialisation-dans-les-calculs-approchés-et-lapprentissage-automatique-ckks">4ème Génération : Spécialisation dans les calculs approchés et l&amp;rsquo;apprentissage automatique (CKKS)
&lt;/h3>&lt;p>Le schéma &lt;strong>CKKS (Cheon-Kim-Kim-Song)&lt;/strong> proposé par Cheon et al. en 2017 est actuellement considéré comme la technologie ultime pour la protection de la vie privée dans l&amp;rsquo;IA et l&amp;rsquo;apprentissage automatique.
Contrairement aux FHE précédents qui se concentraient sur les « calculs entiers exacts », CKKS supporte les &lt;strong>« calculs approchés de nombres à virgule flottante »&lt;/strong> tout en conservant le chiffrement. Il offre des performances écrasantes dans les calculs de nombres réels où de petites erreurs sont tolérées, comme la formation ou l&amp;rsquo;inférence des réseaux de neurones.&lt;/p>
&lt;p>Le tableau ci-dessous résume comment choisir un schéma en fonction de l&amp;rsquo;objectif.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Nom du Schéma&lt;/th>
&lt;th style="text-align:left">Type de Données Préféré&lt;/th>
&lt;th style="text-align:left">Cas d&amp;rsquo;Utilisation Recommandés&lt;/th>
&lt;th style="text-align:left">Caractéristiques&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>BFV / BGV&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Entiers (Integer)&lt;/td>
&lt;td style="text-align:left">Calculs statistiques exacts, agrégation de données financières, recherche dans des bases de données&lt;/td>
&lt;td style="text-align:left">Haut débit grâce au traitement par lots SIMD&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>CKKS&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Nombres réels (Real/Complex)&lt;/td>
&lt;td style="text-align:left">Apprentissage automatique (DNN, régression logistique), traitement du signal&lt;/td>
&lt;td style="text-align:left">Accélération par calculs approchés, redimensionnement&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>TFHE&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Valeurs booléennes (Boolean)&lt;/td>
&lt;td style="text-align:left">N&amp;rsquo;importe quel circuit logique, recherche de chaînes de caractères, évaluation de fonctions non linéaires&lt;/td>
&lt;td style="text-align:left">Bootstrapping ultra-rapide (de l&amp;rsquo;ordre de la milliseconde)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="6-pratique--bibliothèques-fhe-et-code-conceptuel">6. Pratique : Bibliothèques FHE et code conceptuel
&lt;/h2>&lt;p>Aujourd&amp;rsquo;hui, il existe de nombreuses bibliothèques open-source permettant d&amp;rsquo;utiliser le FHE sans nécessiter une connaissance approfondie de la cryptographie.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Microsoft SEAL (Simple Encrypted Arithmetic Library)&lt;/strong> : Une bibliothèque C++ supportant BFV, BGV et CKKS. C&amp;rsquo;est l&amp;rsquo;une des normes de l&amp;rsquo;industrie. Son binding Python, &lt;strong>TenSEAL&lt;/strong>, est très populaire parmi les ingénieurs en IA.&lt;/li>
&lt;li>&lt;strong>Zama (Concrete)&lt;/strong> : Un framework basé sur TFHE. Il peut être écrit en Rust/Python et fournit la fonctionnalité de compiler des modèles PyTorch existants pour les exécuter sur le FHE (Concrete ML).&lt;/li>
&lt;li>&lt;strong>OpenFHE&lt;/strong> : Le successeur de PALISADE, c&amp;rsquo;est une bibliothèque C++ complète qui supporte tous les principaux schémas.&lt;/li>
&lt;/ul>
&lt;h3 id="exemple-de-programmation-fhe-avec-python-tenseal">Exemple de programmation FHE avec Python (TenSEAL)
&lt;/h3>&lt;p>Ici, nous présentons un exemple conceptuel de code Python utilisant le schéma CKKS pour additionner et multiplier des vecteurs de nombres réels tout en les gardant chiffrés.&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-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">tenseal&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">ts&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. Configuration du contexte (incluant la génération des clés)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Utilise le schéma CKKS et définit le degré du polynôme à 8192&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">SCHEME_TYPE&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CKKS&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">poly_modulus_degree&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8192&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">coeff_mod_bit_sizes&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">60&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">60&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="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">generate_galois_keys&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">global_scale&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">40&lt;/span> &lt;span class="c1"># Facteur d&amp;#39;échelle pour les nombres réels&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. Côté client : Chiffrement des données&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vector1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">1.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">2.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">3.5&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vector2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">3.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">4.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"># Convertit les vecteurs en texte clair en textes chiffrés (initialement exécuté côté client)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_v1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ckks_vector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vector1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_v2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ckks_vector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vector2&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. Côté serveur : Opérations tout en gardant le chiffrement (Protection des Data in Use)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Le serveur ne connaît pas le texte clair, mais peut effectuer des additions et des multiplications&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_add&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_v1&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">enc_v2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_mul&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_v1&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">enc_v2&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"># 4. Côté client : Déchiffrement des résultats&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Seul le client possédant la clé privée peut voir le résultat&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">res_add&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_add&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decrypt&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">res_mul&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_mul&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decrypt&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;Résultat de l&amp;#39;addition déchiffrée : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">res_add&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="c1"># Exemple de sortie : [3.5000001, 5.5000001, 7.5000002] (Comprend de légères erreurs dues au calcul approché)&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;Résultat de la multiplication déchiffrée : &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">res_mul&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="c1"># Exemple de sortie : [3.0000002, 7.5000005, 14.0000003]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Comme on peut le voir dans le code ci-dessus, les opérateurs Python normaux comme &lt;code>enc_v1 + enc_v2&lt;/code> peuvent être surchargés pour écrire des calculs entre des textes chiffrés de manière intuitive. Du côté du serveur, l&amp;rsquo;opération vectorielle est réalisée sans jamais connaître le contenu du vecteur.&lt;/p>
&lt;hr>
&lt;h2 id="7-les-défis-du-fhe--performances-et-accélération-matérielle">7. Les défis du FHE : Performances et Accélération Matérielle
&lt;/h2>&lt;p>Le FHE offre une sécurité théoriquement parfaite, mais son plus grand défi en matière d&amp;rsquo;application pratique est la &lt;strong>« surcharge de performances »&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Surcharge de calcul&lt;/strong> : Comparés aux calculs en texte clair, les calculs sur les textes chiffrés sont des milliers à des dizaines de milliers de fois plus lents sur un CPU. La multiplication de polynômes et le bootstrapping nécessitent d&amp;rsquo;énormes calculs de FFT (Transformée de Fourier Rapide) et de NTT (Transformée Théorique des Nombres).&lt;/li>
&lt;li>&lt;strong>Expansion de la taille des données (Ciphertext Expansion)&lt;/strong> : Quelques octets de texte clair peuvent devenir plusieurs mégaoctets une fois chiffrés. Cela exerce une forte pression sur la bande passante de la mémoire et du réseau.&lt;/li>
&lt;/ol>
&lt;h3 id="approches-de-résolution-basées-sur-le-matériel">Approches de résolution basées sur le matériel
&lt;/h3>&lt;p>Pour surmonter cette surcharge, des accélérateurs matériels dédiés au FHE (supportant ASIC, FPGA, GPU) sont en cours de développement dans le monde entier.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Accélération GPU&lt;/strong> : Des efforts sont en cours pour paralléliser les calculs NTT et le bootstrapping à l&amp;rsquo;aide de GPU puissants de NVIDIA et d&amp;rsquo;autres, rapportant des accélérations de plusieurs dizaines de fois par rapport aux implémentations logicielles (par exemple : 100x.ai, le backend CUDA TFHE-rs de Zama).&lt;/li>
&lt;li>&lt;strong>Projet DARPA DPRIVE&lt;/strong> : La Defense Advanced Research Projects Agency (DARPA) mène un projet de développement matériel dédié appelé « DPRIVE (Data Protection in Virtual Environments) » visant à ramener la vitesse de calcul du FHE à un niveau équivalent à celui du traitement en texte clair (une surcharge inférieure à 10 fois), avec la participation d&amp;rsquo;entreprises telles qu&amp;rsquo;Intel, Microsoft et Intellectual Ventures.&lt;/li>
&lt;li>&lt;strong>L&amp;rsquo;émergence du FPU (FHE Processing Unit)&lt;/strong> : Des startups comme Cornami et Optalysys se lancent dans le développement de puces dédiées au FHE utilisant l&amp;rsquo;informatique optique ou des architectures en silicium spécialisées.&lt;/li>
&lt;/ul>
&lt;p>Dans un avenir proche, tout comme pour les NPU (Neural Processing Unit) en IA, nous pourrions voir une époque où les « FPU » deviendront des équipements standard dans les serveurs et les infrastructures cloud.&lt;/p>
&lt;hr>
&lt;h2 id="8-cas-dutilisation-attendus">8. Cas d&amp;rsquo;utilisation attendus
&lt;/h2>&lt;p>Maintenant que le FHE atteint des vitesses pratiques, des innovations disruptives sont attendues dans les domaines suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Protection de la vie privée dans le domaine médical et l&amp;rsquo;analyse génomique&lt;/strong> :
En utilisant le FHE pour former l&amp;rsquo;IA dans le cloud sur des dossiers médicaux et des données ADN de patients provenant de plusieurs hôpitaux tout en conservant les données chiffrées, il est possible de développer des modèles de diagnostic du cancer très précis et de nouveaux médicaments sans violer les lois sur la vie privée (comme HIPAA ou le RGPD).&lt;/li>
&lt;li>&lt;strong>Détection des fraudes et lutte contre le blanchiment d&amp;rsquo;argent (AML) dans les institutions financières&lt;/strong> :
Des banques concurrentes pourraient effectuer des analyses interbancaires en croisant leurs données à l&amp;rsquo;état chiffré, sans révéler les informations des comptes de leurs clients ou l&amp;rsquo;historique de leurs transactions, ce qui permettrait de détecter d&amp;rsquo;énormes réseaux de transferts frauduleux.&lt;/li>
&lt;li>&lt;strong>API d&amp;rsquo;inférence d&amp;rsquo;IA sécurisée (MaaS : Model as a Service)&lt;/strong> :
Les utilisateurs chiffrent leur propre voix, l&amp;rsquo;image de leur visage ou leurs requêtes avant de les envoyer à des services d&amp;rsquo;IA (tels que des LLM comme ChatGPT). Le fournisseur d&amp;rsquo;IA génère une réponse sans jamais connaître l&amp;rsquo;entrée de l&amp;rsquo;utilisateur, et la renvoie sous forme de texte chiffré. Cela dissipe complètement la crainte que « l&amp;rsquo;IA apprenne ou s&amp;rsquo;approprie des informations personnelles ».&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="9-conclusion--lavenir-de-la-cryptographie-se-dirige-vers-le--calcul-invisible-">9. Conclusion : L&amp;rsquo;avenir de la cryptographie se dirige vers le « calcul invisible »
&lt;/h2>&lt;p>Tout comme l&amp;rsquo;invention de la cryptographie à clé publique (RSA) dans les années 1970 a rendu possible des communications sécurisées sur Internet (comme le HTTPS), l&amp;rsquo;invention du FHE par Craig Gentry constitue l&amp;rsquo;une des étapes les plus importantes de l&amp;rsquo;histoire de la cryptographie.&lt;/p>
&lt;p>Aujourd&amp;rsquo;hui, le Chiffrement Homomorphe Complet (FHE) est sorti de la théorie des laboratoires, et des entreprises telles que Microsoft, IBM, Intel, Google et de nombreuses startups se font une concurrence féroce pour le rendre pratique. Bien que des défis liés aux coûts de calcul et à la taille des données subsistent, grâce au raffinement des algorithmes et à l&amp;rsquo;évolution des accélérateurs matériels, les performances continuent de s&amp;rsquo;améliorer à un rythme dépassant la loi de Moore.&lt;/p>
&lt;p>Dans quelques années, « effectuer des calculs sur des données tout en les gardant chiffrées » ne sera plus quelque chose de spécial, mais deviendra une bonne pratique standard en matière de protection des données dans les services cloud. Le FHE est la clé de la sécurité de nouvelle génération qui réalise &lt;strong>l&amp;rsquo;équilibre ultime entre la vie privée et l&amp;rsquo;utilisation des données&lt;/strong> dans une société axée sur les données.&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><item><title>【Illustration PQC】 Comparaison des principaux algorithmes de la cryptographie post-quantique</title><link>http://kenji.blog/fr/p/post-quantum-cryptography-algorithms-comparison/</link><pubDate>Fri, 11 Sep 2026 07:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/post-quantum-cryptography-algorithms-comparison/</guid><description>&lt;img src="http://kenji.blog/p/post-quantum-cryptography-algorithms-comparison/img/eyecatch.jpg" alt="Featured image of post 【Illustration PQC】 Comparaison des principaux algorithmes de la cryptographie post-quantique" />&lt;h2 id="1-introduction--la--crise-de-la-cryptographie--provoquée-par-les-ordinateurs-quantiques">1. Introduction : La « crise de la cryptographie » provoquée par les ordinateurs quantiques
&lt;/h2>&lt;p>Dans la société Internet moderne, la cryptographie à clé publique est une infrastructure indispensable pour protéger la confidentialité des communications et l&amp;rsquo;intégrité des données. Les méthodes de cryptographie largement utilisées aujourd&amp;rsquo;hui, telles que RSA et la cryptographie sur les courbes elliptiques (ECC), reposent sur des barrières mathématiques telles que la « difficulté de la factorisation de très grands nombres composés » ou la « difficulté du problème du logarithme discret sur les courbes elliptiques » pour garantir leur sécurité. Avec les ordinateurs classiques (les ordinateurs que nous utilisons actuellement, y compris les superordinateurs), il a été prouvé qu&amp;rsquo;il faudrait plus de temps que l&amp;rsquo;âge de l&amp;rsquo;univers pour résoudre ces problèmes mathématiques, ce qui constitue le fondement de leur sécurité.&lt;/p>
&lt;p>Cependant, cette prémisse solide est sur le point d&amp;rsquo;être fondamentalement bouleversée par l&amp;rsquo;avancée de la théorie et de la mise en pratique des &lt;strong>ordinateurs quantiques&lt;/strong>. En 1994, l&amp;rsquo;algorithme de Shor, publié par le cryptographe Peter Shor (« &lt;strong>Algorithme de Shor&lt;/strong> »), a prouvé théoriquement que les problèmes de factorisation et de logarithme discret pourraient être résolus en « temps polynomial » s&amp;rsquo;ils étaient exécutés sur un ordinateur quantique universel tolérant aux pannes (CRQC : Cryptographically Relevant Quantum Computer) d&amp;rsquo;une capacité suffisante. Cela signifie que toutes les cryptographies à clé publique utilisées actuellement seront rendues inefficaces.&lt;/p>
&lt;div class="mermaid">graph TD
A["Ordinateur quantique à grande échelle (CRQC)"] -->|Exécution| B["Algorithme de Shor"]
B -->|Déchiffrement en temps polynomial| C["Problème de factorisation en nombres premiers (RSA)"]
B -->|Déchiffrement en temps polynomial| D["Problème du logarithme discret (ECC / ECDSA)"]
C --> E["Écoute de communications chiffrées, altération de données, usurpation d'identité"]
D --> E
F["Store Now, Decrypt Later (SNDL)"] --> E&lt;/div>
&lt;p>Il est très dangereux de penser que « l&amp;rsquo;achèvement à grande échelle des ordinateurs quantiques n&amp;rsquo;est pas prévu avant plusieurs décennies, il n&amp;rsquo;y a donc pas de problème ». En effet, la méthode d&amp;rsquo;attaque appelée &lt;strong>Store Now, Decrypt Later (SNDL : Stocker maintenant, déchiffrer plus tard)&lt;/strong> est déjà une menace réelle. Il s&amp;rsquo;agit d&amp;rsquo;une attaque dans laquelle des États malveillants ou des groupes de pirates stockent massivement les données de communication chiffrées actuelles (comme le trafic TLS) sur des supports de stockage, afin de les déchiffrer toutes dès qu&amp;rsquo;un ordinateur quantique puissant sera disponible à l&amp;rsquo;avenir. Les secrets d&amp;rsquo;État, les informations d&amp;rsquo;infrastructure et les données médicales qui doivent être protégées à long terme sont déjà exposés à cette menace.&lt;/p>
&lt;p>De plus, il existe l&amp;rsquo;&lt;strong>algorithme de Grover&lt;/strong>, découvert en 1996, qui s&amp;rsquo;applique à la cryptographie à clé symétrique (comme AES) et aux fonctions de hachage (comme SHA-256). Cet algorithme réduit la complexité de l&amp;rsquo;attaque par force brute à sa racine carrée. En d&amp;rsquo;autres termes, le niveau de sécurité de l&amp;rsquo;AES-128 est effectivement réduit de moitié, pour atteindre 2 à la puissance 64. Par conséquent, à l&amp;rsquo;ère quantique, il est recommandé d&amp;rsquo;utiliser des longueurs de clés et des longueurs de hachage plus grandes, telles que l&amp;rsquo;AES-256 et le SHA-384.&lt;/p>
&lt;p>Pour faire face à cette crise cryptographique sans précédent, une nouvelle &lt;strong>cryptographie post-quantique (Post-Quantum Cryptography : PQC)&lt;/strong> a vu le jour, reposant sur de nouveaux problèmes mathématiques difficiles à déchiffrer même avec des ordinateurs quantiques. Cet article explique de manière très détaillée, sur la base des résultats du processus de standardisation PQC mené par le National Institute of Standards and Technology (NIST) des États-Unis, les principaux algorithmes PQC, depuis leur contexte mathématique jusqu&amp;rsquo;à leurs mécanismes et la comparaison de leurs architectures.&lt;/p>
&lt;hr>
&lt;h2 id="2-aperçu-et-histoire-du-projet-de-standardisation-pqc-par-le-nist">2. Aperçu et histoire du projet de standardisation PQC par le NIST
&lt;/h2>&lt;p>La transition des technologies cryptographiques, qui implique la refonte des protocoles, la mise à jour des systèmes et le remplacement du matériel, prendra des années, voire des décennies. C&amp;rsquo;est pourquoi les cryptographes du monde entier ont commencé très tôt à faire des recherches sur la PQC. Le NIST (National Institute of Standards and Technology) américain a joué un rôle central dans ce domaine. En 2016, le NIST a lancé un appel public pour le processus de standardisation de la PQC et a accepté des propositions de tout nouveaux algorithmes cryptographiques de la part de la communauté cryptographique mondiale.&lt;/p>
&lt;p>Les deux principales catégories ciblées par la standardisation étaient les suivantes :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Cryptographie à clé publique / Mécanisme d&amp;rsquo;encapsulation de clé (KEM : Key Encapsulation Mechanism)&lt;/strong> : Mécanisme permettant de partager (distribuer) en toute sécurité une clé symétrique pour chiffrer le canal de communication dans des connexions telles que TLS.&lt;/li>
&lt;li>&lt;strong>Signatures numériques (Digital Signatures)&lt;/strong> : Mécanisme permettant de prouver, dans les mises à jour logicielles et les certificats électroniques, que les données n&amp;rsquo;ont pas été altérées et qu&amp;rsquo;il n&amp;rsquo;y a pas d&amp;rsquo;usurpation d&amp;rsquo;identité de l&amp;rsquo;expéditeur (authenticité).&lt;/li>
&lt;/ol>
&lt;p>Après environ six années de concurrence acharnée en matière d&amp;rsquo;évaluation, d&amp;rsquo;analyse et de cryptanalyse (Round 1 à Round 3), une évaluation supplémentaire (Round 4) a été menée pour certains algorithmes. En conséquence, les algorithmes suivants ont été officiellement publiés en tant que Federal Information Processing Standards (FIPS) en 2024, s&amp;rsquo;établissant comme les futures normes mondiales.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FIPS 203 (ML-KEM)&lt;/strong> : KEM basé sur CRYSTALS-Kyber&lt;/li>
&lt;li>&lt;strong>FIPS 204 (ML-DSA)&lt;/strong> : Signature numérique basée sur CRYSTALS-Dilithium&lt;/li>
&lt;li>&lt;strong>FIPS 205 (SLH-DSA)&lt;/strong> : Signature basée sur le hachage sans état (stateless) reposant sur SPHINCS+&lt;/li>
&lt;li>&lt;strong>(À formuler ultérieurement) FN-DSA&lt;/strong> : Signature numérique basée sur FALCON&lt;/li>
&lt;/ul>
&lt;p>Ces algorithmes sélectionnés reposent chacun sur des « problèmes de difficulté » mathématiques différents. Ainsi, si une vulnérabilité fatale venait à être découverte dans l&amp;rsquo;un des algorithmes à l&amp;rsquo;avenir, la diversité (Crypto Agility) est assurée pour éviter que l&amp;rsquo;ensemble du système ne s&amp;rsquo;effondre. Dans le processus de standardisation, la cryptographie basée sur les réseaux (Lattice-based cryptography) a joué le rôle principal en raison de ses performances, mais la cryptographie basée sur le hachage et la cryptographie basée sur les codes ont été adoptées comme de solides solutions de secours.&lt;/p>
&lt;hr>
&lt;h2 id="3-classification-des-principales-approches-mathématiques-de-la-pqc">3. Classification des principales approches mathématiques de la PQC
&lt;/h2>&lt;p>Les algorithmes PQC sont principalement classés en cinq catégories en fonction des problèmes mathématiques qui sous-tendent leur sécurité. Dans cet article, nous approfondirons particulièrement les trois premiers.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Cryptographie basée sur les réseaux (Lattice-based Cryptography)&lt;/strong> :
Elle repose sur le problème du vecteur le plus court (SVP) et le problème du vecteur le plus proche (CVP) dans un espace de réseau multidimensionnel, ainsi que sur le problème LWE qui en dérive. Elle est au cœur de la standardisation du NIST, et Kyber, Dilithium et FALCON en font partie. Elle offre le meilleur équilibre entre la vitesse de traitement, la taille de la clé publique et la taille du texte chiffré, ce qui la rend adaptée à une utilisation polyvalente.&lt;/li>
&lt;li>&lt;strong>Cryptographie basée sur le hachage (Hash-based Cryptography)&lt;/strong> :
Elle fonde sa sécurité uniquement sur la « résistance aux collisions » et la « propriété unidirectionnelle » des fonctions de hachage cryptographique (telles que SHA-2 et SHAKE). Bien qu&amp;rsquo;elle ne soit applicable qu&amp;rsquo;aux signatures numériques (comme SPHINCS+), ses preuves de sécurité sont les plus robustes et elle se caractérise par une résistance extrêmement élevée aux attaques mathématiques inconnues.&lt;/li>
&lt;li>&lt;strong>Cryptographie basée sur les codes (Code-based Cryptography)&lt;/strong> :
Basée sur la théorie des codes correcteurs d&amp;rsquo;erreurs, elle dépend de la difficulté du problème du décodage de syndrome (Syndrome Decoding Problem). Le Classic McEliece, proposé dans les années 1970, en est représentatif et possède une très longue histoire et une sécurité éprouvée, bien que la taille de la clé publique soit extrêmement importante (de l&amp;rsquo;ordre du mégaoctet).&lt;/li>
&lt;li>&lt;strong>Cryptographie polynomiale multivariée (Multivariate Polynomial Cryptography)&lt;/strong> :
Elle repose sur la difficulté de résoudre des systèmes d&amp;rsquo;équations quadratiques à plusieurs variables sur un corps fini (problème MQ). Principalement proposée pour les signatures numériques (comme Rainbow), une méthode d&amp;rsquo;attaque puissante permettant de la déchiffrer en quelques jours sur un simple PC a été découverte lors du dernier round du NIST, entraînant l&amp;rsquo;élimination de nombreux algorithmes de la standardisation.&lt;/li>
&lt;li>&lt;strong>Cryptographie basée sur les isogénies (Isogeny-based Cryptography)&lt;/strong> :
Elle repose sur le problème de recherche de chemin sur des graphes d&amp;rsquo;isogénies de courbes elliptiques. Avec des tailles de clé très petites, elle était attendue comme le successeur légitime de l&amp;rsquo;ECC, mais « SIKE », le candidat final, a été complètement déchiffré en seulement quelques heures sur un PC normal en 2022 à l&amp;rsquo;aide de mathématiques classiques (comme l&amp;rsquo;attaque de Castryck-Decru), symbolisant la fin dramatique, ainsi que la difficulté et le danger liés à la conception de la PQC.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-les-abysses-de-la-cryptographie-sur-les-réseaux--les-bases-mathématiques-du-problème-lwe-et-du-module-lwe">4. Les abysses de la cryptographie sur les réseaux : Les bases mathématiques du problème LWE et du Module-LWE
&lt;/h2>&lt;p>Considérée aujourd&amp;rsquo;hui comme la plus prometteuse et devenue le centre de la standardisation, voici la &lt;strong>cryptographie basée sur les réseaux (Lattice cryptography)&lt;/strong>. À la base de sa sécurité se trouve le &lt;strong>problème LWE (Learning with Errors : Apprentissage avec erreurs)&lt;/strong>. Proposé par Oded Regev en 2005, cette réalisation historique lui a valu le prix Gödel. Il est impossible de parler de la PQC moderne sans comprendre le problème LWE.&lt;/p>
&lt;h3 id="41-quest-ce-que-le-problème-lwe-learning-with-errors-">4.1. Qu&amp;rsquo;est-ce que le problème LWE (Learning with Errors) ?
&lt;/h3>&lt;p>Considérons tout d&amp;rsquo;abord un simple système d&amp;rsquo;équations linéaires. Sous un certain module $q$ (modulo $q$), supposons que nous ayons une matrice aléatoire connue $A$, un vecteur secret inconnu $\vec{s}$, et que leur produit $\vec{b}$ soit donné.&lt;/p>
$$ \vec{b} = A\vec{s} \pmod q $$
&lt;p>Dans ce cas, il est facile de trouver le vecteur inconnu $\vec{s}$ à partir des informations publiques $A$ et $\vec{b}$. En utilisant un algorithme classique comme « l&amp;rsquo;élimination de Gauss (ou pivot de Gauss) », on peut facilement calculer $\vec{s}$ en temps polynomial.&lt;/p>
&lt;p>Cependant, si l&amp;rsquo;on ajoute à cette équation une « petite erreur intentionnelle (bruit) », le niveau de difficulté du problème augmente considérablement. C&amp;rsquo;est ce qu&amp;rsquo;on appelle le &lt;strong>problème LWE&lt;/strong>.&lt;/p>
&lt;p>On prépare un vecteur secret inconnu $\vec{s} \in \mathbb{Z}_q^n$ et une matrice choisie au hasard $A \in \mathbb{Z}_q^{m \times n}$. De plus, un vecteur d&amp;rsquo;erreur $\vec{e} \in \mathbb{Z}_q^m$ dont « la valeur des éléments est suffisamment petite » est choisi selon une distribution normale ou binomiale, et $\vec{b}$ est calculé comme suit.&lt;/p>
$$ \vec{b} = A\vec{s} + \vec{e} \pmod q $$
&lt;p>Le &lt;strong>problème Search LWE (LWE de recherche)&lt;/strong> consiste à « trouver l&amp;rsquo;information secrète $\vec{s}$ à partir des informations publiques $(A, \vec{b})$ ». En raison de la présence de cette erreur $\vec{e}$, toute tentative d&amp;rsquo;utiliser des méthodes de résolution algébriques telles que l&amp;rsquo;élimination de Gauss fera que l&amp;rsquo;erreur $\vec{e}$ s&amp;rsquo;amplifiera de manière exponentielle lors de l&amp;rsquo;addition et de la soustraction des équations, devenant finalement indiscernable d&amp;rsquo;une valeur aléatoire et conduisant à un échec.&lt;/p>
&lt;p>La puissance du problème LWE réside dans le fait qu&amp;rsquo;il existe une forte preuve théorique (réduction) affirmant que le problème LWE ne peut pas non plus être résolu en moyenne (Average-case), à moins qu&amp;rsquo;il n&amp;rsquo;existe un algorithme quantique capable de résoudre le problème du plus court vecteur de décision (GapSVP) ou le problème des vecteurs indépendants les plus courts (SIVP), qui sont des problèmes de « complexité dans le pire des cas (Worst-case hardness) » sur les réseaux. En d&amp;rsquo;autres termes, même pour des clés de chiffrement générées aléatoirement, une sécurité robuste, soutenue par des limites théoriques, est garantie.&lt;/p>
&lt;h3 id="42-amélioration-drastique-de-lefficacité-grâce-à-ring-lwe-et-module-lwe">4.2. Amélioration drastique de l&amp;rsquo;efficacité grâce à Ring-LWE et Module-LWE
&lt;/h3>&lt;p>Le problème LWE normal (Standard LWE) a une base de sécurité très claire, mais n&amp;rsquo;est pas pratique car la taille de la matrice $A$ devient très grande et les tailles de clés atteignent le niveau du mégaoctet. L&amp;rsquo;approche proposée a donc été d&amp;rsquo;utiliser des anneaux de polynômes (Polynomial Rings) pour lui donner une structure algébrique.&lt;/p>
&lt;p>Dans le &lt;strong>problème Ring-LWE&lt;/strong>, on utilise des éléments (polynômes) d&amp;rsquo;un certain anneau de polynômes $R_q$ au lieu de simples vecteurs et matrices. Dans la norme NIST, l&amp;rsquo;anneau de polynômes cyclotomiques suivant est généralement utilisé.&lt;/p>
$$ R_q = \mathbb{Z}_q[X]/(X^n + 1) $$
&lt;p>Ici, $n$ est une puissance de 2 (par exemple 256) et $q$ est un nombre premier approprié. Sur cet anneau, on calcule $b = a \cdot s + e \pmod q$ en utilisant les éléments $a, s, e \in R_q$. Comme un seul polynôme $a$ possède $n$ coefficients, les données peuvent être considérablement compressées. De plus, l&amp;rsquo;utilisation d&amp;rsquo;une version de transformée de Fourier rapide (FFT) sur corps fini, appelée &lt;strong>NTT (Number Theoretic Transform : Transformée de la théorie des nombres)&lt;/strong>, permet une multiplication de polynômes ultra-rapide avec une complexité de calcul de $O(n \log n)$.&lt;/p>
&lt;p>Cependant, il y avait des inquiétudes concernant le Ring-LWE quant à « l&amp;rsquo;existence possible de vulnérabilités inconnues dues à la structure algébrique spécifique de l&amp;rsquo;anneau ». Il y avait également le défi d&amp;rsquo;ingénierie selon lequel, lors de la modification du niveau de sécurité (par exemple, équivalent à AES-128, 192, 256), il fallait modifier le degré $n$ du polynôme lui-même, ce qui nécessitait de réécrire l&amp;rsquo;ensemble de l&amp;rsquo;implémentation, y compris l&amp;rsquo;algorithme NTT.&lt;/p>
&lt;p>C&amp;rsquo;est pourquoi les algorithmes standardisés Kyber et Dilithium ont adopté le &lt;strong>problème Module-LWE (M-LWE)&lt;/strong>. Le Module-LWE est un compromis situé exactement entre le Standard LWE sans structure et le Ring-LWE qui possède trop de structure, en utilisant une matrice de taille $k \times k$ (module) dont les composants sont les éléments de l&amp;rsquo;anneau de polynômes $R_q$.&lt;/p>
$$ \vec{b} = A\vec{s} + \vec{e} \pmod{R_q} \quad (A \in R_q^{k \times k}, \vec{s}, \vec{e} \in R_q^k) $$
&lt;p>Le plus grand avantage du Module-LWE est qu&amp;rsquo;il permet de faire évoluer facilement le niveau de sécurité en modifiant simplement la dimension $k$ de la matrice, tout en gardant fixe le degré $n$ du polynôme (dans la norme NIST, $n=256$).
Par exemple, pour Kyber, la dimension $k$ est ajustée de la manière suivante :&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Kyber512 (Niveau 1)&lt;/strong> : $k = 2$ (équivalent AES-128)&lt;/li>
&lt;li>&lt;strong>Kyber768 (Niveau 3)&lt;/strong> : $k = 3$ (équivalent AES-192)&lt;/li>
&lt;li>&lt;strong>Kyber1024 (Niveau 5)&lt;/strong> : $k = 4$ (équivalent AES-256)&lt;/li>
&lt;/ul>
&lt;p>Cela a permis de réutiliser à 100 % le code NTT sous-jacent et le circuit matériel des opérations polynomiales pour tous les niveaux de sécurité, ce qui a permis d&amp;rsquo;améliorer considérablement la sécurité et l&amp;rsquo;efficacité de l&amp;rsquo;implémentation.&lt;/p>
&lt;hr>
&lt;h2 id="5-crystals-kyber-ml-kem--le-mécanisme-dencapsulation-de-clé-de-nouvelle-génération">5. CRYSTALS-Kyber (ML-KEM) : Le mécanisme d&amp;rsquo;encapsulation de clé de nouvelle génération
&lt;/h2>&lt;p>Officiellement standardisé sous le nom de &lt;strong>FIPS 203 (ML-KEM)&lt;/strong>, CRYSTALS-Kyber est un mécanisme d&amp;rsquo;encapsulation de clé (KEM) basé sur le problème Module-LWE susmentionné. Il s&amp;rsquo;agira de la norme mondiale de facto pour le partage sécurisé des clés de session à l&amp;rsquo;avenir, notamment pour TLS 1.3 et SSH.&lt;/p>
&lt;h3 id="51-architecture-du-kem-key-encapsulation-mechanism">5.1. Architecture du KEM (Key Encapsulation Mechanism)
&lt;/h3>&lt;p>À l&amp;rsquo;ère de la PQC, l&amp;rsquo;approche directe telle que RSA où « le client crée une clé partagée, la chiffre avec la clé publique du serveur et l&amp;rsquo;envoie » est remplacée par le cadre d&amp;rsquo;encapsulation appelé KEM.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Client as "Client (Alice)"
participant Server as "Serveur (Bob)"
Note over Client: "ML-KEM KeyGen()"
Client->>Client: "Générer la clé secrète (sk) et la clé publique (pk)"
Client->>Server: "Envoyer la clé publique (pk)"
Note over Server: "ML-KEM Encaps()"
Server->>Server: "Générer une clé partagée aléatoire (K)"
Server->>Server: "Encapsuler K avec pk pour créer le texte chiffré (c)"
Server->>Client: "Envoyer le texte chiffré (c)"
Note over Client: "ML-KEM Decaps()"
Client->>Client: "Déchiffrer le texte chiffré (c) à l'aide de la clé secrète (sk)"
Client->>Client: "Désencapsuler et extraire la clé partagée (K)"
Note over Client, Server: "Commencer la communication chiffrée (par ex. AES) avec la clé partagée (K)"&lt;/div>
&lt;h3 id="52-fonctionnement-interne-de-kyber-et-transformation-de-fujisaki-okamoto">5.2. Fonctionnement interne de Kyber et Transformation de Fujisaki-Okamoto
&lt;/h3>&lt;p>La conception de Kyber est extrêmement raffinée. Tout d&amp;rsquo;abord, un schéma de chiffrement à clé publique (Kyber.CPAPKE), sûr uniquement contre les attaques à texte clair choisi (CPA), est construit, puis une technique cryptographique très puissante appelée &lt;strong>Transformation de Fujisaki-Okamoto (Fujisaki-Okamoto Transform)&lt;/strong> est appliquée, ce qui permet de le faire évoluer vers un KEM complet et sûr contre les attaques à chiffré choisi adaptatif (CCA).&lt;/p>
&lt;p>Le mécanisme de chiffrement et de déchiffrement au cœur de CPAPKE est le suivant :&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Génération de clé (Key Generation)&lt;/strong> :&lt;/p>
&lt;ul>
&lt;li>À partir d&amp;rsquo;une valeur de graine aléatoire (seed), générer une matrice $A \in R_q^{k \times k}$ sur le domaine NTT. Le modulo $q$ utilisé est $3329$.&lt;/li>
&lt;li>Échantillonner un vecteur secret $\vec{s}$ et un vecteur d&amp;rsquo;erreur $\vec{e}$ avec de petits coefficients à partir d&amp;rsquo;une distribution binomiale centrée (CBD).&lt;/li>
&lt;li>Calculer $\vec{t} = A\vec{s} + \vec{e}$. La clé publique est $(A, \vec{t})$ et la clé secrète est $\vec{s}$. (En pratique, $A$ est publiée en tant que valeur de graine (seed) pour économiser de la bande passante).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Chiffrement (Encryption)&lt;/strong> :&lt;/p>
&lt;ul>
&lt;li>Encoder le message de 32 octets (matériau de la clé partagée) $m$ que l&amp;rsquo;on souhaite partager en un polynôme.&lt;/li>
&lt;li>Générer un nouveau vecteur aléatoire $\vec{r}$ et de petites erreurs $\vec{e_1}, e_2$.&lt;/li>
&lt;li>$\vec{u} = A^T\vec{r} + \vec{e_1}$&lt;/li>
&lt;li>$v = \vec{t}^T\vec{r} + e_2 + \lfloor q/2 \rceil \cdot m$&lt;/li>
&lt;li>Le texte chiffré est $(\vec{u}, v)$.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Déchiffrement (Decryption)&lt;/strong> :&lt;/p>
&lt;ul>
&lt;li>Le destinataire calcule $v - \vec{s}^T\vec{u}$.&lt;/li>
&lt;li>Le développement de cette équation donne ce qui suit.
$v - \vec{s}^T\vec{u} = (\vec{t}^T\vec{r} + e_2 + \lfloor q/2 \rceil \cdot m) - \vec{s}^T(A^T\vec{r} + \vec{e_1})$&lt;/li>
&lt;li>En remplaçant $\vec{t} = A\vec{s} + \vec{e}$, le terme principal $\vec{s}^TA^T\vec{r}$ s&amp;rsquo;annule.&lt;/li>
&lt;li>Il reste $\lfloor q/2 \rceil \cdot m + (\vec{e}^T\vec{r} + e_2 - \vec{s}^T\vec{e_1})$.&lt;/li>
&lt;li>Les termes entre parenthèses étant des « produits ou sommes de petites erreurs », l&amp;rsquo;ensemble reste une valeur (bruit) suffisamment petite. Par conséquent, en déterminant si chaque coefficient est proche de $0$ ou de $q/2$, les bits (0 ou 1) du message d&amp;rsquo;origine $m$ peuvent être parfaitement restaurés sans aucune erreur.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>La plus grande force de Kyber réside dans sa &lt;strong>vitesse de traitement&lt;/strong> impressionnante et sa &lt;strong>taille de clé modérée&lt;/strong>. Pour Kyber768, la taille de la clé publique est de 1 184 octets et la taille du texte chiffré est de 1 088 octets. Bien qu&amp;rsquo;elles soient plus importantes par rapport à RSA-3072 (taille de clé d&amp;rsquo;environ 384 octets), il est possible de les faire tenir dans l&amp;rsquo;unité de transmission maximale (MTU) des communications Internet modernes sans fragmentation des paquets, ce qui n&amp;rsquo;a presque aucun impact négatif sur la latence du réseau.&lt;/p>
&lt;hr>
&lt;h2 id="6-crystals-dilithium-ml-dsa--signature-numérique-polyvalente-basée-sur-les-réseaux">6. CRYSTALS-Dilithium (ML-DSA) : Signature numérique polyvalente basée sur les réseaux
&lt;/h2>&lt;p>Dans la standardisation des signatures numériques, des algorithmes avec différentes philosophies de conception ont concouru au sein de la même approche de la cryptographie sur les réseaux. Parmi eux, &lt;strong>CRYSTALS-Dilithium&lt;/strong> a été sélectionné comme signature numérique polyvalente sous le nom de &lt;strong>FIPS 204 (ML-DSA)&lt;/strong>.&lt;/p>
&lt;h3 id="61-le-paradigme-fiat-shamir-with-aborts">6.1. Le paradigme Fiat-Shamir with Aborts
&lt;/h3>&lt;p>Comme Kyber, Dilithium est un schéma de signature numérique basé sur le problème Module-LWE (ainsi que sur le problème Module-SIS). À la base de sa conception, le paradigme extrêmement important appelé « &lt;strong>Fiat-Shamir with Aborts (Transformation de Fiat-Shamir avec rejets)&lt;/strong> » est utilisé.&lt;/p>
&lt;p>La transformation de Fiat-Shamir elle-même est une méthode standard pour convertir un protocole interactif de preuve à divulgation nulle (zero-knowledge proof) en une signature numérique non interactive. Le prouveur (signataire) génère un engagement (commitment) $y$, calcule $w = Ay$ et le passe par une fonction de hachage pour obtenir un défi aléatoire $c$, puis calcule la réponse $z = y + cs$.&lt;/p>
&lt;p>Cependant, dans la cryptographie sur les réseaux, l&amp;rsquo;application naïve de cette méthode entraînait un problème fatal (fuite mathématique de type canal auxiliaire) où la distribution de la réponse $z$ devenait asymétrique en fonction de la valeur de la clé secrète $s$, et un attaquant observant de nombreuses signatures obtiendrait peu à peu des informations sur la clé secrète $s$.&lt;/p>
&lt;p>L&amp;rsquo;équipe de conception de Dilithium (Lyubashevsky et al.) a introduit une technique appelée « &lt;strong>Échantillonnage par rejet (Rejection Sampling)&lt;/strong> » : si les coefficients du résultat de la signature $z$ ne tombent pas dans une plage de seuil de sécurité prédéfinie, l&amp;rsquo;ensemble du processus de signature est abandonné (Abort) et le calcul est recommencé depuis le début en utilisant un nouveau nombre aléatoire $y$.&lt;/p>
&lt;p>Grâce à cela, la signature finale produite $z$ est une distribution complètement uniforme qui ne dépend en aucun cas de la clé secrète, réussissant à prévenir complètement la fuite d&amp;rsquo;informations sur le plan mathématique.&lt;/p>
&lt;h3 id="62-les-avantages-de-dilithium-et-la-facilité-de-son-implémentation">6.2. Les avantages de Dilithium et la facilité de son implémentation
&lt;/h3>&lt;p>Le grand avantage de la conception de Dilithium est qu&amp;rsquo;elle n&amp;rsquo;utilise &lt;strong>absolument pas&lt;/strong> d&amp;rsquo;« échantillonnage complexe à partir de distributions gaussiennes » ou d&amp;rsquo;« opérations en virgule flottante » dans le processus de génération de signature. Puisqu&amp;rsquo;il peut être mis en œuvre uniquement avec un échantillonnage à partir d&amp;rsquo;une distribution uniforme, des opérations simples en modulo entier, des NTT et des fonctions de hachage (SHAKE), il est facile de l&amp;rsquo;implémenter de manière sécurisée et en temps constant (Constant-time) dans un large éventail d&amp;rsquo;environnements, allant des microcontrôleurs embarqués aux serveurs cloud. De ce fait, il possède également une forte résistance contre les attaques physiques par canal auxiliaire, telles que les attaques par chronométrage (timing attacks).&lt;/p>
&lt;hr>
&lt;h2 id="7-falcon-fn-dsa--signature-sur-réseaux-ultra-compacte">7. FALCON (FN-DSA) : Signature sur réseaux ultra-compacte
&lt;/h2>&lt;p>Le NIST a sélectionné &lt;strong>FALCON (Fast-Fourier Lattice-based Compact Signatures over NTRU)&lt;/strong> comme autre candidat standard de signature basée sur les réseaux, avec des caractéristiques différentes de celles de Dilithium (actuellement en cours de rédaction en tant que FN-DSA).&lt;/p>
&lt;h3 id="71-réseaux-ntru-et-échantillonnage-gaussien">7.1. Réseaux NTRU et échantillonnage gaussien
&lt;/h3>&lt;p>La plus grande caractéristique de FALCON est qu&amp;rsquo;il n&amp;rsquo;utilise pas le problème LWE, mais plutôt le &lt;strong>réseau NTRU (N-th degree Truncated polynomial Ring Units)&lt;/strong>, très ancien et existant depuis 1996. De plus, il adopte le paradigme « &lt;strong>Hash-and-Sign (Hachage et Signature)&lt;/strong> » basé sur le framework GPV (Gentry-Peikert-Vaikuntanathan).&lt;/p>
&lt;p>Dans Hash-and-Sign, la valeur de hachage du message est utilisée comme point cible dans l&amp;rsquo;espace, et le point sur le réseau le plus proche de ce point (une solution approchée du problème du vecteur le plus proche) est trouvé pour servir de signature. Pour cela, il est nécessaire d&amp;rsquo;échantillonner des points selon une distribution gaussienne discrète en utilisant une « base courte de bonne qualité » qui est la clé secrète.&lt;/p>
&lt;p>FALCON a considérablement accéléré ce calcul intensif en utilisant une technique appelée « &lt;strong>Orthogonalisation de Fourier rapide (Fast Fourier Orthogonalization : FFO)&lt;/strong> ».&lt;/p>
&lt;h3 id="72-avantages-et-inconvénients-de-falcon">7.2. Avantages et inconvénients de FALCON
&lt;/h3>&lt;p>L&amp;rsquo;avantage écrasant de FALCON réside dans le fait que &lt;strong>la taille de sa signature et la taille de sa clé publique sont extrêmement petites (compactes)&lt;/strong>. Alors que la taille de la signature de Dilithium3 est d&amp;rsquo;environ 3 309 octets, celle de FALCON-512 n&amp;rsquo;est que d&amp;rsquo;environ 666 octets. La clé publique est également très petite, avec 897 octets, ce qui en fait un sauveur dans les environnements où la bande passante de communication est extrêmement limitée, pour les appareils IoT et dans certains protocoles réseau.&lt;/p>
&lt;p>Cependant, il existe un inconvénient majeur. Puisque l&amp;rsquo;échantillonnage gaussien discret impliquant des &lt;strong>opérations complexes en virgule flottante (64-bit IEEE 754)&lt;/strong> est indispensable lors de la génération de la signature, l&amp;rsquo;implémentation en temps constant (Constant-time implementation) pour prévenir les fuites de temps est extrêmement difficile, et le code devient énorme. C&amp;rsquo;est pourquoi FALCON est positionné comme un puissant algorithme spécialisé pour des usages spécifiques, par opposition à l&amp;rsquo;utilisation polyvalente (Dilithium).&lt;/p>
&lt;div class="mermaid">graph LR
A["Exigences en matière de signatures numériques"] --> B{"Quelle est la contrainte prioritaire ?"}
B -->|"Simplicité d'implémentation, polyvalence, facilité d'implémentation en temps constant"| C["Dilithium (ML-DSA)"]
B -->|"Minimisation de la bande passante de communication, compacité de la taille des données"| D["FALCON (FN-DSA)"]
C --> E["Certificats TLS génériques, signature électronique de logiciels"]
D --> F["Protocoles avec des limites strictes de taille de paquet, environnements spéciaux"]&lt;/div>
&lt;hr>
&lt;h2 id="8-sphincs-slh-dsa--signature-basée-sur-le-hachage-offrant-la-plus-forte-sécurité">8. SPHINCS+ (SLH-DSA) : Signature basée sur le hachage offrant la plus forte sécurité
&lt;/h2>&lt;p>Pour se préparer au pire des scénarios (le cas échéant) où la sécurité de la cryptographie sur les réseaux serait brisée à l&amp;rsquo;avenir par une percée d&amp;rsquo;un brillant mathématicien, le NIST a formulé &lt;strong>FIPS 205 (SLH-DSA)&lt;/strong>, c&amp;rsquo;est-à-dire &lt;strong>SPHINCS+&lt;/strong>, en tant que norme basée sur une approche complètement différente de celle de la cryptographie sur les réseaux.&lt;/p>
&lt;p>SPHINCS+ est classé comme une &lt;strong>signature basée sur le hachage&lt;/strong>. Sa sécurité repose uniquement sur un seul point : « la fonction de hachage cryptographique utilisée (comme SHA-2 ou SHAKE256) possède une résistance aux collisions et une propriété unidirectionnelle ». Contrairement au LWE ou à la factorisation, qui dépendent de problèmes mathématiques possédant des structures algébriques spécifiques, SPHINCS+ peut faire face à n&amp;rsquo;importe quel algorithme quantique puissant qui pourrait apparaître à l&amp;rsquo;avenir, simplement en allongeant la longueur de sortie de la fonction de hachage. Il s&amp;rsquo;enorgueillit ainsi d&amp;rsquo;une sécurité extrêmement robuste (la sécurité la plus conservatrice).&lt;/p>
&lt;h3 id="81-architecture-sans-état-stateless-avec-wots-et-fors">8.1. Architecture sans état (stateless) avec WOTS+ et FORS
&lt;/h3>&lt;p>L&amp;rsquo;histoire des signatures basées sur le hachage est ancienne et remonte aux signatures Lamport et aux signatures à usage unique (One-Time Signatures) Winternitz (WOTS) des années 1970. Il s&amp;rsquo;agissait de clés jetables où « l&amp;rsquo;on ne peut signer en toute sécurité qu&amp;rsquo;une seule fois ». Afin de pouvoir les utiliser plusieurs fois, des algorithmes tels que XMSS (eXtended Merkle Signature Scheme) et LMS ont été développés en combinant des arbres de Merkle pour gérer d&amp;rsquo;innombrables clés à usage unique avec un seul hachage racine.&lt;/p>
&lt;p>Cependant, XMSS et LMS présentaient un défaut majeur : ils étaient « &lt;strong>avec état (stateful)&lt;/strong> ». Chaque fois qu&amp;rsquo;une signature était effectuée, il était nécessaire de conserver un enregistrement strict de l&amp;rsquo;état de l&amp;rsquo;index « quelle clé à usage unique a été utilisée » dans une mémoire non volatile. Si l&amp;rsquo;état était restauré (par exemple, par la restauration d&amp;rsquo;un snapshot de machine virtuelle) et que la même clé à usage unique était utilisée deux fois, la clé secrète serait immédiatement divulguée et le système s&amp;rsquo;effondrerait.&lt;/p>
&lt;p>SPHINCS+ est une signature basée sur le hachage « &lt;strong>sans état (stateless)&lt;/strong> » qui a résolu les tracas liés à la gestion des états.
Sa technologie de base est la combinaison suivante :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>WOTS+ (Winternitz One-Time Signature Plus)&lt;/strong> : Signature à usage unique de base.&lt;/li>
&lt;li>&lt;strong>FORS (Forest of Random Subsets)&lt;/strong> : Technologie de signature à faible fréquence d&amp;rsquo;utilisation (Few-Time Signature). La sécurité est maintenue même si la même clé est réutilisée un petit nombre de fois.&lt;/li>
&lt;li>&lt;strong>Hyper-Tree (Structure arborescente géante)&lt;/strong> : Structure géante composée de plusieurs couches d&amp;rsquo;arbres de Merkle empilées.&lt;/li>
&lt;/ol>
&lt;p>Dans SPHINCS+, lors de la signature, au lieu de gérer des états, une clé FORS est sélectionnée de manière aléatoire parmi un nombre colossal de clés au bas de l&amp;rsquo;Hyper-Tree à l&amp;rsquo;aide d&amp;rsquo;un nombre pseudo-aléatoire pour effectuer la signature. Étant donné que le nombre de feuilles de l&amp;rsquo;arbre est astronomique, la probabilité de sélectionner la même clé deux fois par accident (collision) est si faible qu&amp;rsquo;elle peut être ignorée, ce qui permet d&amp;rsquo;atteindre l&amp;rsquo;absence d&amp;rsquo;état (stateless).&lt;/p>
&lt;p>La seule et plus grande faiblesse de SPHINCS+ est que &lt;strong>la taille de sa signature est extrêmement grande&lt;/strong>. Selon les paramètres, la taille de la signature peut atteindre 17 kilo-octets à 49 kilo-octets, et la vitesse de génération des signatures est également très lente par rapport à la cryptographie sur les réseaux. Par conséquent, il est prévu de l&amp;rsquo;utiliser dans des applications nécessitant une sécurité absolue à long terme et où les signatures ne sont pas effectuées fréquemment, telles que les signatures de mise à jour logicielle et les certificats d&amp;rsquo;Autorité de Certification (CA) racine, plutôt que pour la navigation Web quotidienne.&lt;/p>
&lt;hr>
&lt;h2 id="9-cryptographie-basée-sur-les-codes--classic-mceliece-le-bon-vieux-géant">9. Cryptographie basée sur les codes : Classic McEliece, le bon vieux géant
&lt;/h2>&lt;p>Dans le processus de standardisation du NIST, &lt;strong>Classic McEliece&lt;/strong>, de la &lt;strong>cryptographie basée sur les codes&lt;/strong>, est une approche importante dont l&amp;rsquo;évaluation se poursuit toujours en tant que candidat final de la phase 4.&lt;/p>
&lt;p>Proposé par Robert McEliece en 1978, cet algorithme est l&amp;rsquo;un des plus anciens de l&amp;rsquo;histoire de la cryptographie à clé publique, aux côtés du RSA. Il utilise des codes de géométrie algébrique appelés « codes de Goppa », qui ajoutent intentionnellement une erreur (vecteur de bruit) au message lors du chiffrement. Seule la personne possédant la matrice de contrôle de parité du code de Goppa comme clé secrète peut utiliser sa puissante capacité de correction d&amp;rsquo;erreurs pour supprimer l&amp;rsquo;erreur et déchiffrer le message d&amp;rsquo;origine, un principe basé sur le « &lt;strong>problème du décodage de syndrome (Syndrome Decoding Problem)&lt;/strong> ».&lt;/p>
$$ \vec{c} = \vec{m} G + \vec{e} $$
&lt;p>
（$G$ est la matrice génératrice brouillée qui est la clé publique, et $\vec{e}$ est le vecteur d&amp;rsquo;erreur de poids $t$）&lt;/p>
&lt;p>Ce qui est surprenant avec Classic McEliece, c&amp;rsquo;est son bilan impressionnant : &lt;strong>bien que plus de 40 ans se soient écoulés depuis sa proposition et qu&amp;rsquo;il ait fait l&amp;rsquo;objet d&amp;rsquo;intenses recherches de déchiffrement par des cryptographes du monde entier, aucune vulnérabilité intrinsèque n&amp;rsquo;y a jamais été découverte&lt;/strong>. Il possède la « sécurité éprouvée par le temps » la plus solide de toute la PQC.&lt;/p>
&lt;p>De plus, il a l&amp;rsquo;avantage d&amp;rsquo;avoir une taille de texte chiffré très petite (seulement 100 à 200 octets). Cependant, il présente un défaut majeur : &lt;strong>la taille de la clé publique est en mégaoctets (Mo)&lt;/strong>. Même pour le niveau de sécurité le plus bas (équivalent à AES-128), la clé publique est d&amp;rsquo;environ 250 Ko, et elle dépasse 1 Mo pour des niveaux plus élevés.&lt;/p>
&lt;p>Pour cette raison, il est totalement inadapté aux applications qui envoient des clés publiques sur le réseau à chaque communication, telles que les poignées de main TLS. Cependant, pour des cas d&amp;rsquo;utilisation spécifiques où la clé publique peut être placée à l&amp;rsquo;avance dans le système, comme l&amp;rsquo;échange de clés pré-partagées pour les VPN, le codage en dur de clés publiques dans le firmware ou la communication par satellite, il continue d&amp;rsquo;être considéré comme une option très prometteuse en raison de sa forte sécurité.&lt;/p>
&lt;hr>
&lt;h2 id="10-comparaison-des-performances-et-compromis-de-chaque-algorithme-pqc">10. Comparaison des performances et compromis de chaque algorithme PQC
&lt;/h2>&lt;p>Le tableau suivant résume les caractéristiques de performance des principaux algorithmes abordés jusqu&amp;rsquo;à présent à des niveaux de sécurité courants (équivalents aux niveaux 2 à 3 du NIST, soit le niveau AES-128 à 192).&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Algorithme (Nom standard)&lt;/th>
&lt;th style="text-align:left">Catégorie&lt;/th>
&lt;th style="text-align:left">Base mathématique&lt;/th>
&lt;th style="text-align:left">Taille de la clé publique&lt;/th>
&lt;th style="text-align:left">Taille de la clé secrète&lt;/th>
&lt;th style="text-align:left">Taille du chiffré/signature&lt;/th>
&lt;th style="text-align:left">Tendance de la vitesse de traitement&lt;/th>
&lt;th style="text-align:left">Principales caractéristiques et utilisations&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Kyber768&lt;/strong>&lt;br>(ML-KEM)&lt;/td>
&lt;td style="text-align:left">KEM&lt;/td>
&lt;td style="text-align:left">Module-LWE&lt;/td>
&lt;td style="text-align:left">1 184 octets&lt;/td>
&lt;td style="text-align:left">2 400 octets&lt;/td>
&lt;td style="text-align:left">1 088 octets&lt;/td>
&lt;td style="text-align:left">Très rapide&lt;/td>
&lt;td style="text-align:left">Meilleur équilibre entre taille de clé et vitesse. Norme KEM générique comme TLS 1.3.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Dilithium3&lt;/strong>&lt;br>(ML-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">Module-LWE&lt;/td>
&lt;td style="text-align:left">1 952 octets&lt;/td>
&lt;td style="text-align:left">4 032 octets&lt;/td>
&lt;td style="text-align:left">3 309 octets&lt;/td>
&lt;td style="text-align:left">Génération et vérification rapides&lt;/td>
&lt;td style="text-align:left">Implémentation simple. Norme de signature numérique polyvalente.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>FALCON-512&lt;/strong>&lt;br>(FN-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">Réseaux NTRU&lt;/td>
&lt;td style="text-align:left">897 octets&lt;/td>
&lt;td style="text-align:left">1 281 octets&lt;/td>
&lt;td style="text-align:left">666 octets&lt;/td>
&lt;td style="text-align:left">Génération plus lente, vérification ultra-rapide&lt;/td>
&lt;td style="text-align:left">Taille de signature minime. Nécessite des opérations en virgule flottante. Pour IoT/embarqué.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>SPHINCS+&lt;/strong>&lt;br>(SLH-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">Fonction de hachage&lt;/td>
&lt;td style="text-align:left">32 octets&lt;/td>
&lt;td style="text-align:left">64 octets&lt;/td>
&lt;td style="text-align:left">Env. 17 000 octets&lt;/td>
&lt;td style="text-align:left">Génération très lente&lt;/td>
&lt;td style="text-align:left">Risque mathématique quasi nul. Pour applications de haute sécurité comme certificats racine.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Classic McEliece&lt;/strong>&lt;/td>
&lt;td style="text-align:left">KEM&lt;/td>
&lt;td style="text-align:left">Codes de Goppa&lt;/td>
&lt;td style="text-align:left">&lt;strong>Env. 1.04 Mo&lt;/strong>&lt;/td>
&lt;td style="text-align:left">13 568 octets&lt;/td>
&lt;td style="text-align:left">&lt;strong>188 octets&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Encapsulation rapide&lt;/td>
&lt;td style="text-align:left">40 ans de sécurité éprouvée. Clé publique énorme. Pour environnements avec codage en dur.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="comprendre-les-compromis">Comprendre les compromis
&lt;/h3>&lt;p>Dans le monde de la PQC, il n&amp;rsquo;existe pas d&amp;rsquo;algorithme unique et magique qui soit « petit en taille, rapide, et avec des garanties mathématiques parfaites ».&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Les normes d&amp;rsquo;Internet (Kyber / Dilithium)&lt;/strong> : Elles offrent le meilleur équilibre des performances et sont les mieux adaptées au remplacement direct (drop-in replacement) du RSA et de l&amp;rsquo;ECC actuels.&lt;/li>
&lt;li>&lt;strong>La conservativité ultime (SPHINCS+)&lt;/strong> : Elle est choisie lorsque l&amp;rsquo;on souhaite une assurance absolue contre les futures percées mathématiques, même au prix de la taille des données et de la vitesse de traitement.&lt;/li>
&lt;li>&lt;strong>Pour des environnements spécifiques (FALCON / Classic McEliece)&lt;/strong> : Ce sont des armes spécialisées choisies en fonction des contraintes de l&amp;rsquo;environnement, telles que des bandes passantes de communication extrêmement étroites ou la possibilité d&amp;rsquo;une distribution préalable.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="11-défis-vers-la-mise-en-pratique-et-la-solution-réaliste-de-la--cryptographie-hybride-">11. Défis vers la mise en pratique et la solution réaliste de la « cryptographie hybride »
&lt;/h2>&lt;p>Avec l&amp;rsquo;achèvement de la standardisation par le NIST et la publication officielle des normes FIPS, la transition mondiale de l&amp;rsquo;infrastructure informatique vers la PQC (&lt;strong>Migration PQC&lt;/strong>) a véritablement commencé. Le navigateur Chrome de Google, iMessage d&amp;rsquo;Apple (protocole PQ3) et les fournisseurs de réseaux comme Cloudflare ont déjà implémenté le support de la PQC dans leurs protocoles et ont commencé leur exploitation commerciale.&lt;/p>
&lt;p>Cependant, basculer soudainement et complètement vers de nouveaux algorithmes de cryptographie comporte des risques très élevés. Si un brillant mathématicien venait à découvrir dans quelques années une faille mathématique fatale dans la cryptographie sur les réseaux (comme Kyber) qui pourrait être résolue même par un ordinateur classique, l&amp;rsquo;ensemble des systèmes qui en dépendent seraient instantanément exposés.&lt;/p>
&lt;p>L&amp;rsquo;approche réaliste et recommandée pour atténuer ce risque d&amp;rsquo;incertitude est la « &lt;strong>cryptographie hybride (Hybrid Cryptography)&lt;/strong> ».&lt;/p>
&lt;p>Dans la cryptographie hybride, l&amp;rsquo;échange de clés est effectué en utilisant simultanément les cryptographies classiques actuelles ayant fait leurs preuves depuis longtemps (par exemple, la cryptographie sur courbe elliptique comme X25519) et les nouvelles PQC (par exemple, Kyber768). Les composants de la clé partagée sont générés individuellement par chaque algorithme, puis enfin, une fonction de dérivation de clé (KDF) sécurisée est utilisée pour mélanger les deux composants et générer le secret maître final.&lt;/p>
&lt;div class="mermaid">graph TD
A["Client"] -->|① Envoi de la clé publique X25519 + clé publique Kyber| B["Serveur"]
B -->|② Réponse avec clé partagée X25519 + chiffré encapsulé Kyber| A
A --> C{"Dérivation du secret maître (KDF)"}
B --> C
C -->|"Entrée : (Clé partagée X25519) || (Clé partagée Kyber)"| D["Clé de communication sécurisée (AES-256 / ChaCha20)"]
D -->|"Résistance aux menaces quantiques ET aux vulnérabilités classiques"| E["Communication chiffrée hybride sécurisée (TLS 1.3)"]&lt;/div>
&lt;p>Grâce à cela, il est possible d&amp;rsquo;atteindre une sécurité robuste à deux niveaux : « même si un ordinateur quantique est réalisé et que l&amp;rsquo;ECC est brisé, Kyber protège la communication », et inversement, « même si un défaut mathématique inconnu est trouvé dans Kyber, l&amp;rsquo;ECC protège la communication ». Un exemple typique est le brouillon &lt;strong>X25519MLKEM768 (anciennement X25519Kyber768)&lt;/strong> en cours de standardisation à l&amp;rsquo;IETF, et la communication entre les navigateurs Web actuels et les serveurs de pointe est précisément réalisée à l&amp;rsquo;aide de cette méthode hybride.&lt;/p>
&lt;p>De plus, le concept de &lt;strong>Crypto Agility (Agilité cryptographique)&lt;/strong>, qui consiste à concevoir des systèmes avec « une architecture qui ne dépend pas excessivement d&amp;rsquo;un algorithme cryptographique spécifique et qui permet de basculer rapidement vers un autre algorithme (par exemple, de Kyber à McEliece, de Dilithium à SPHINCS+) en cas de compromission de l&amp;rsquo;algorithme », deviendra une exigence indispensable dans le développement futur des systèmes.&lt;/p>
&lt;hr>
&lt;h2 id="12-conclusion--un-nouvel-horizon-pour-les-technologies-cryptographiques">12. Conclusion : Un nouvel horizon pour les technologies cryptographiques
&lt;/h2>&lt;p>Paradoxalement, l&amp;rsquo;ordinateur quantique, la technologie de rêve de l&amp;rsquo;humanité, est devenu la plus grande menace, capable de briser les barrières mathématiques telles que la « factorisation en nombres premiers » et le « problème du logarithme discret » sur lesquelles nous nous reposons depuis de nombreuses années. Cependant, les cryptographes du monde entier ne se sont pas avoués vaincus et ont exploré des domaines mathématiques multidimensionnels plus complexes et profonds, tels que la théorie des réseaux, les arbres de fonctions de hachage et les codes correcteurs d&amp;rsquo;erreurs, pour bâtir une nouvelle barrière : la cryptographie post-quantique (PQC).&lt;/p>
&lt;p>L&amp;rsquo;achèvement de la standardisation des normes FIPS 203 (ML-KEM), FIPS 204 (ML-DSA) et FIPS 205 (SLH-DSA) par le NIST n&amp;rsquo;est pas une ligne d&amp;rsquo;arrivée. Ce n&amp;rsquo;est que la première étape d&amp;rsquo;un voyage épique de migration vers la PQC qui durera plusieurs décennies. Pour les ingénieurs logiciels et les architectes système, le grand défi technique de l&amp;rsquo;avenir consistera à adapter au mieux l&amp;rsquo;« augmentation de la taille des clés » et les « changements de coûts de calcul » apportés par ces nouveaux algorithmes aux protocoles réseau et aux systèmes.&lt;/p>
&lt;p>La bataille entre l&amp;rsquo;ordinateur quantique et la cryptographie est un domaine passionnant où la quête mathématique de l&amp;rsquo;humanité et l&amp;rsquo;évolution technologique se croisent de la manière la plus intense. À travers cet article, nous espérons que vous aurez acquis une compréhension approfondie de la belle théorie mathématique qui sous-tend la PQC, ainsi que des mécanismes surprenants de chaque algorithme qui façonnera l&amp;rsquo;avenir de la cybersécurité.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Références :&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;em>NIST Post-Quantum Cryptography Standardization Program&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 204: Module-Lattice-Based Digital Signature Standard&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 205: Stateless Hash-Based Digital Signature Standard&lt;/em>&lt;/li>
&lt;/ul></description></item></channel></rss>