<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ECC on kenji.blog</title><link>http://kenji.blog/fr/tags/ecc/</link><description>Recent content in ECC on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 10:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/ecc/index.xml" rel="self" type="application/rss+xml"/><item><title>Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++</title><link>http://kenji.blog/fr/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/elliptic-curve-cryptography-math-cpp/</guid><description>&lt;img src="http://kenji.blog/p/elliptic-curve-cryptography-math-cpp/img/eyecatch.jpg" alt="Featured image of post Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++" />&lt;h1 id="fondements-mathématiques-de-la-cryptographie-sur-les-courbes-elliptiques-ecc-et-implémentation-en-c">Fondements mathématiques de la cryptographie sur les courbes elliptiques (ECC) et implémentation en C++
&lt;/h1>&lt;p>Dans les technologies de cryptographie modernes, la &lt;strong>cryptographie sur les courbes elliptiques (Elliptic Curve Cryptography : ECC)&lt;/strong> joue un rôle extrêmement important. De nos communications Internet quotidiennes (HTTPS/TLS) aux enclaves sécurisées des smartphones, en passant par l&amp;rsquo;authentification des serveurs via SSH, l&amp;rsquo;authentification sans mot de passe comme FIDO, et même les crypto-actifs tels que Bitcoin et Ethereum, on peut dire sans exagérer que la base de confiance de la société numérique moderne est soutenue par l&amp;rsquo;ECC.&lt;/p>
&lt;p>Dans cet article, nous expliquerons en profondeur, avec un volume de contenu impressionnant, le fonctionnement de cette cryptographie sur les courbes elliptiques. Nous partirons de la théorie mathématique sous-jacente, belle mais complexe (géométrie algébrique sur les corps finis), pour aller jusqu&amp;rsquo;à la méthode d&amp;rsquo;implémentation réelle en C++, et enfin aux techniques de codage sécurisé pour prévenir les attaques par canaux auxiliaires (attaques temporelles).&lt;/p>
&lt;hr>
&lt;h2 id="1-pourquoi-la-cryptographie-sur-les-courbes-elliptiques--comparaison-avec-rsa">1. Pourquoi la cryptographie sur les courbes elliptiques ? (Comparaison avec RSA)
&lt;/h2>&lt;p>Pendant longtemps, le synonyme de cryptographie à clé publique a été la &lt;strong>cryptographie RSA&lt;/strong>. La sécurité de RSA repose sur la &amp;ldquo;difficulté de la factorisation en nombres premiers de très grands nombres composés&amp;rdquo;. Cependant, avec l&amp;rsquo;amélioration de la puissance de calcul des ordinateurs, il a été nécessaire d&amp;rsquo;allonger continuellement la taille des clés RSA (le nombre de bits du module) pour maintenir la sécurité. Aujourd&amp;rsquo;hui, une taille de clé d&amp;rsquo;au moins 2048 bits est recommandée, voire 3072 bits ou 4096 bits pour plus de sécurité.&lt;/p>
&lt;p>En revanche, la cryptographie sur les courbes elliptiques (ECC) repose sur une autre difficulté mathématique appelée le &lt;strong>&amp;ldquo;problème du logarithme discret sur les courbes elliptiques (ECDLP)&amp;rdquo;&lt;/strong>. Jusqu&amp;rsquo;à présent, aucun algorithme efficace (comme les algorithmes en temps sous-exponentiel) pour résoudre l&amp;rsquo;ECDLP n&amp;rsquo;a été découvert, et même les méthodes d&amp;rsquo;attaque les plus efficaces connues nécessitent un temps exponentiel.&lt;/p>
&lt;p>Grâce à cette propriété, l&amp;rsquo;ECC possède l&amp;rsquo;avantage décisif de &lt;strong>pouvoir atteindre un niveau de sécurité équivalent à celui de RSA avec une taille de clé beaucoup plus courte&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">Niveau de sécurité (bits)&lt;/th>
&lt;th style="text-align:center">Taille de clé RSA (bits)&lt;/th>
&lt;th style="text-align:center">Taille de clé ECC (bits)&lt;/th>
&lt;th style="text-align:center">Ratio des tailles de clé&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">80&lt;/td>
&lt;td style="text-align:center">1024&lt;/td>
&lt;td style="text-align:center">160&lt;/td>
&lt;td style="text-align:center">1:6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">112&lt;/td>
&lt;td style="text-align:center">2048&lt;/td>
&lt;td style="text-align:center">224&lt;/td>
&lt;td style="text-align:center">1:9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">128&lt;/td>
&lt;td style="text-align:center">3072&lt;/td>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">1:12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">192&lt;/td>
&lt;td style="text-align:center">7680&lt;/td>
&lt;td style="text-align:center">384&lt;/td>
&lt;td style="text-align:center">1:20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">15360&lt;/td>
&lt;td style="text-align:center">512&lt;/td>
&lt;td style="text-align:center">1:30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Comme le montre le tableau ci-dessus, pour obtenir un niveau de sécurité de 128 bits (le standard actuel), RSA nécessite une clé de 3072 bits, alors que l&amp;rsquo;ECC ne nécessite que 256 bits. Cela permet de réduire la quantité de calculs, l&amp;rsquo;utilisation de la mémoire et d&amp;rsquo;économiser la bande passante du réseau. L&amp;rsquo;ECC présente ainsi une supériorité écrasante, en particulier dans les environnements aux ressources limitées comme les appareils IoT et les cartes à puce.&lt;/p>
&lt;hr>
&lt;h2 id="2-prérequis-mathématiques--la-théorie-des-groupes-et-le-monde-des-corps-finis">2. Prérequis mathématiques : La théorie des groupes et le monde des corps finis
&lt;/h2>&lt;p>Pour véritablement comprendre la cryptographie sur les courbes elliptiques, il est nécessaire de maîtriser les concepts de base de l&amp;rsquo;algèbre abstraite (théorie des groupes et théorie des corps). Nous résumons ici brièvement les connaissances préalables pour construire l&amp;rsquo;ECC.&lt;/p>
&lt;h3 id="21-groupes-group-et-groupes-abéliens">2.1. Groupes (Group) et Groupes abéliens
&lt;/h3>&lt;p>Un &lt;strong>groupe (Group)&lt;/strong> est défini par un ensemble $G$ et une opération binaire sur cet ensemble (nous utiliserons ici l&amp;rsquo;addition $+$) formant une paire $(G, +)$ qui satisfait aux 4 axiomes suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Clôture (Closure)&lt;/strong> : Pour tous $a, b \in G$, $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>Associativité (Associativity)&lt;/strong> : Pour tous $a, b, c \in G$, $(a + b) + c = a + (b + c)$.&lt;/li>
&lt;li>&lt;strong>Existence de l&amp;rsquo;élément neutre (Identity element)&lt;/strong> : Il existe un élément $e \in G$ tel que pour tout $a \in G$, $a + e = e + a = a$. Dans le cas d&amp;rsquo;un groupe additif, cet élément neutre est généralement noté $0$ ou $\mathcal{O}$.&lt;/li>
&lt;li>&lt;strong>Existence de l&amp;rsquo;inverse (Inverse element)&lt;/strong> : Pour tout $a \in G$, il existe un élément $b \in G$ tel que $a + b = b + a = e$. Ce $b$ est noté $-a$.&lt;/li>
&lt;/ol>
&lt;p>De plus, un groupe qui satisfait la condition suivante, où l&amp;rsquo;ordre des opérations ne change pas le résultat, est appelé un &lt;strong>groupe abélien (ou groupe commutatif)&lt;/strong> :&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>Commutativité (Commutativity)&lt;/strong> : Pour tous $a, b \in G$, $a + b = b + a$.&lt;/li>
&lt;/ol>
&lt;p>L&amp;rsquo;ensemble des points sur une courbe elliptique forme ce &lt;strong>groupe abélien&lt;/strong> en définissant une règle d&amp;rsquo;addition spécifique.&lt;/p>
&lt;h3 id="22-corps-finis-finite-field">2.2. Corps finis (Finite Field)
&lt;/h3>&lt;p>Dans la théorie cryptographique, nous n&amp;rsquo;utilisons pas des corps ayant un nombre infini et continu d&amp;rsquo;éléments comme les nombres réels ou complexes, mais plutôt des &lt;strong>corps finis (Finite Field)&lt;/strong> ou corps de Galois (Galois Field), dont le nombre d&amp;rsquo;éléments est fini.&lt;/p>
&lt;p>Le corps fini le plus fondamental est le &lt;strong>corps premier $\mathbb{F}_p$&lt;/strong> utilisant un nombre premier $p$. Il s&amp;rsquo;agit de l&amp;rsquo;ensemble des entiers $\{0, 1, 2, \dots, p-1\}$ muni des quatre opérations arithmétiques (addition, soustraction, multiplication, division) définies modulo $p$ (le reste de la division par $p$).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Addition&lt;/strong> : $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Soustraction&lt;/strong> : $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Multiplication&lt;/strong> : $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Division&lt;/strong> : $a \times b^{-1} \pmod p$ (où $b^{-1}$ est l&amp;rsquo;inverse multiplicatif de $b$ modulo $p$)&lt;/li>
&lt;/ul>
&lt;p>Le calcul de l&amp;rsquo;&lt;strong>inverse multiplicatif (Modular Multiplicative Inverse)&lt;/strong> est extrêmement important dans l&amp;rsquo;implémentation cryptographique. Pour trouver $b^{-1}$ satisfaisant $b \times b^{-1} \equiv 1 \pmod p$, les deux algorithmes suivants sont principalement utilisés :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Algorithme d&amp;rsquo;Euclide étendu (Extended Euclidean Algorithm)&lt;/strong> : Il est rapide, mais selon l&amp;rsquo;implémentation, le temps de traitement dépend des valeurs d&amp;rsquo;entrée, ce qui présente un risque d&amp;rsquo;attaque temporelle.&lt;/li>
&lt;li>&lt;strong>Petit théorème de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong> : Lorsque $p$ est un nombre premier et $b \neq 0$, $b^{p-1} \equiv 1 \pmod p$ est vrai. En divisant les deux côtés par $b$, on obtient $b^{p-2} \equiv b^{-1} \pmod p$. Autrement dit, l&amp;rsquo;inverse peut être trouvé en calculant $b$ à la puissance $p-2$. Comme l&amp;rsquo;opération d&amp;rsquo;exponentiation est plus facile à implémenter en temps constant, elle est préférée dans les implémentations cryptographiques.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-léquation-de-la-courbe-elliptique-et-géométrie">3. L&amp;rsquo;équation de la courbe elliptique et géométrie
&lt;/h2>&lt;h3 id="31-forme-normale-de-weierstrass">3.1. Forme normale de Weierstrass
&lt;/h3>&lt;p>Une &lt;strong>courbe elliptique (Elliptic Curve)&lt;/strong> est une courbe plane généralement définie par l&amp;rsquo;équation suivante, appelée &lt;strong>forme normale de Weierstrass (Weierstrass normal form)&lt;/strong> :&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>Ici, $a$ et $b$ sont des constantes, et pour que la courbe n&amp;rsquo;ait pas de points singuliers (auto-intersections ou points de rebroussement) (pour qu&amp;rsquo;elle soit une courbe lisse), la condition est que le &lt;strong>discriminant (Discriminant) $\Delta$&lt;/strong> suivant ne soit pas nul :&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>Les courbes avec des points singuliers compromettent la sécurité cryptographique, c&amp;rsquo;est pourquoi on choisit toujours des coefficients $a, b$ qui satisfont à cette condition.&lt;/p>
&lt;h3 id="32-le-point-à-linfini-point-at-infinity">3.2. Le point à l&amp;rsquo;infini (Point at Infinity)
&lt;/h3>&lt;p>Pour faire de la courbe elliptique un groupe mathématiquement complet, en plus des points sur le plan, un point virtuel appelé &lt;strong>&amp;ldquo;point à l&amp;rsquo;infini (Point at Infinity)&amp;rdquo;&lt;/strong> est introduit. Il est noté $\mathcal{O}$ (O majuscule).&lt;/p>
&lt;p>Le point à l&amp;rsquo;infini $\mathcal{O}$ est défini comme le point où toutes les lignes verticales se croisent à l&amp;rsquo;infini. Dans la théorie des groupes, ce point à l&amp;rsquo;infini $\mathcal{O}$ fonctionne comme &lt;strong>l&amp;rsquo;élément neutre de l&amp;rsquo;addition&lt;/strong> (zéro).&lt;/p>
&lt;p>Autrement dit, pour tout point $P$ sur la courbe :
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>De plus, l&amp;rsquo;inverse $-P$ du point $P = (x, y)$ est défini comme le point symétrique par rapport à l&amp;rsquo;axe des x, soit $(x, -y)$. Par conséquent :
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;hr>
&lt;h2 id="4-opérations-de-groupe-sur-la-courbe-elliptique-addition-de-points-et-doublement">4. Opérations de groupe sur la courbe elliptique (Addition de points et doublement)
&lt;/h2>&lt;p>Le fondement de la cryptographie sur les courbes elliptiques est l&amp;rsquo;opération d&amp;rsquo;&lt;strong>&amp;ldquo;addition (Addition)&amp;rdquo;&lt;/strong> de points sur la courbe. Ceci est différent de l&amp;rsquo;addition d&amp;rsquo;entiers ordinaires et est défini sur la base d&amp;rsquo;opérations géométriques.&lt;/p>
&lt;h3 id="41-addition-géométrique-méthode-de-la-tangente-et-de-la-sécante">4.1. Addition géométrique (Méthode de la tangente et de la sécante)
&lt;/h3>&lt;p>La procédure pour ajouter deux points distincts $P$ et $Q$ sur la courbe pour obtenir un nouveau point $R$ ($R = P + Q$) est la suivante :&lt;/p>
&lt;ol>
&lt;li>Tracez une ligne droite (sécante) passant par les points $P$ et $Q$.&lt;/li>
&lt;li>Cette droite coupera toujours la courbe elliptique en un autre point (que nous appellerons $-R$). (*Selon un théorème de la géométrie algébrique)&lt;/li>
&lt;li>Le point symétrique de l&amp;rsquo;intersection $-R$ par rapport à l&amp;rsquo;axe des x (le point avec le signe de la coordonnée y inversé) est le point recherché $R$.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["Tracer une droite reliant P(x1, y1) et Q(x2, y2)"] --> Step2["Trouver la 3ème intersection avec la courbe, -R"]
Step2 --> Step3["Refléter -R sur l'axe des x pour obtenir R(x3, y3)"]
Step3 -.-> Result["Ceci est R = P + Q"]&lt;/div>
&lt;h3 id="42-doublement-de-point-point-doubling">4.2. Doublement de point (Point Doubling)
&lt;/h3>&lt;p>Lorsque l&amp;rsquo;on ajoute le même point $P$ à $P$ ($P + P = 2P$), on ne peut pas tracer une ligne passant par deux points. Dans ce cas, nous tracons &lt;strong>la tangente (Tangent) à la courbe au point $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Tracez la tangente à la courbe au point $P$.&lt;/li>
&lt;li>Cette tangente coupera la courbe en un autre point $-R$.&lt;/li>
&lt;li>Le point symétrique de cette intersection par rapport à l&amp;rsquo;axe des x est le point recherché $R = 2P$.&lt;/li>
&lt;/ol>
&lt;h3 id="43-formules-de-calcul-algébrique">4.3. Formules de calcul algébrique
&lt;/h3>&lt;p>Nous transposons les opérations géométriques en formules algébriques afin qu&amp;rsquo;elles puissent être calculées par un ordinateur.
Tous les calculs sont effectués &lt;strong>sur le corps fini $\mathbb{F}_p$ (modulo $p$)&lt;/strong>.&lt;/p>
&lt;p>Soient le point $P = (x_1, y_1)$ et le point $Q = (x_2, y_2)$.
Et soit le point de résultat calculé $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>Soit $\lambda$ (lambda) la pente de la droite.&lt;/p>
&lt;p>&lt;strong>[Cas 1 : Lorsque $P \neq Q$ (Addition de points)]&lt;/strong>
La pente $\lambda$ est le taux de variation entre les deux points.
&lt;/p>
$$ \lambda \equiv \frac{y_2 - y_1}{x_2 - x_1} \pmod p $$
$$ \lambda \equiv (y_2 - y_1) \cdot (x_2 - x_1)^{-1} \pmod p $$
&lt;p>En utilisant ce $\lambda$, $x_3, y_3$ sont calculés comme suit :
&lt;/p>
$$ x_3 \equiv \lambda^2 - x_1 - x_2 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;p>&lt;strong>[Cas 2 : Lorsque $P = Q$ (Doublement de point)]&lt;/strong>
La pente $\lambda$ est la pente de la tangente obtenue par dérivation. (On dérive implicitement $y^2 = x^3 + ax + b$)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
Par conséquent,
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>Les équations pour $x_3, y_3$ ont la même forme que l&amp;rsquo;addition, mais puisque $x_2 = x_1$, elles deviennent :
&lt;/p>
$$ x_3 \equiv \lambda^2 - 2x_1 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;blockquote>
&lt;p>[!IMPORTANT]
Ces formules contiennent des &lt;strong>divisions (calcul de l&amp;rsquo;inverse modulo)&lt;/strong> telles que $(x_2 - x_1)^{-1}$ et $(2y_1)^{-1}$. Le calcul de l&amp;rsquo;inverse modulo ayant un coût de calcul très élevé, les implémentations réelles utilisent généralement des systèmes de coordonnées projectives comme les &lt;strong>&amp;ldquo;coordonnées jacobiennes (Jacobian Coordinates)&amp;rdquo;&lt;/strong> pour retarder la division.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-multiplication-scalaire-et-problème-du-logarithme-discret-sur-les-courbes-elliptiques-ecdlp">5. Multiplication scalaire et problème du logarithme discret sur les courbes elliptiques (ECDLP)
&lt;/h2>&lt;p>Dans la cryptographie sur les courbes elliptiques, l&amp;rsquo;opération qui demande le plus de calculs et qui constitue le cœur de la sécurité est la &lt;strong>multiplication scalaire (Scalar Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="51-quest-ce-que-la-multiplication-scalaire-">5.1. Qu&amp;rsquo;est-ce que la multiplication scalaire ?
&lt;/h3>&lt;p>L&amp;rsquo;opération consistant à additionner un certain point $P$, $k$ fois est appelée multiplication scalaire, notée $kP$.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k\text{ fois}} $$
&lt;p>Ici, $k$ est un très grand nombre entier (par exemple, un entier de 256 bits).&lt;/p>
&lt;h3 id="52-problème-du-logarithme-discret-sur-les-courbes-elliptiques-ecdlp">5.2. Problème du logarithme discret sur les courbes elliptiques (ECDLP)
&lt;/h3>&lt;p>La sécurité de l&amp;rsquo;ECC dépend de la difficulté du problème suivant :&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Problème du logarithme discret sur les courbes elliptiques (Elliptic Curve Discrete Logarithm Problem : ECDLP)&lt;/strong>
Étant donné un point connu $P$ (point de base) et un point calculé $Q$, trouver le scalaire $k$ tel que $Q = kP$.&lt;/p>
&lt;/blockquote>
&lt;p>Il est facile (en temps polynomial) de calculer $Q$ à partir de $k$ et $P$ (sens direct) en utilisant l&amp;rsquo;algorithme décrit plus loin, mais il est pratiquement impossible de calculer à l&amp;rsquo;envers $k$ à partir de $P$ et $Q$ (sens inverse), car il n&amp;rsquo;existe pas de méthode efficace autre que la recherche exhaustive (fonction à sens unique).
Dans les protocoles cryptographiques, &lt;strong>$k$ correspond à la &amp;ldquo;clé privée&amp;rdquo; et $Q$ à la &amp;ldquo;clé publique&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-lalgorithme-double-and-add">5.3. L&amp;rsquo;algorithme Double-and-Add
&lt;/h3>&lt;p>Lorsque $k$ est un nombre énorme (par exemple, $2^{256}$), l&amp;rsquo;addition naïve de $P$ $k$ fois ne se terminerait pas avant la fin de l&amp;rsquo;univers. Par conséquent, pour effectuer rapidement la multiplication scalaire, on utilise la méthode &lt;strong>Double-and-Add (méthode binaire)&lt;/strong>.&lt;/p>
&lt;p>C&amp;rsquo;est la version courbe elliptique de l&amp;rsquo;&amp;ldquo;exponentiation rapide&amp;rdquo; utilisée pour calculer rapidement les puissances entières. Le scalaire $k$ est représenté en binaire, et traité dans l&amp;rsquo;ordre, du bit de poids fort au bit de poids faible.&lt;/p>
&lt;ol>
&lt;li>Initialiser le point de résultat $R$ avec $\mathcal{O}$.&lt;/li>
&lt;li>Répéter ce qui suit du bit de poids fort de $k$ jusqu&amp;rsquo;au bit de poids faible :
&lt;ul>
&lt;li>Doubler $R$ (Point Doubling : $R = 2R$)&lt;/li>
&lt;li>Si le bit actuel est &lt;code>1&lt;/code>, ajouter $P$ à $R$ (Point Addition : $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Grâce à cet algorithme, la complexité passe de $O(k)$ à $O(\log_2 k)$ de façon drastique, permettant des calculs dans un temps réaliste (de l&amp;rsquo;ordre de la milliseconde).&lt;/p>
&lt;hr>
&lt;h2 id="6-léchange-de-clés-diffie-hellman-sur-courbes-elliptiques-ecdh">6. L&amp;rsquo;échange de clés Diffie-Hellman sur courbes elliptiques (ECDH)
&lt;/h2>&lt;p>Nous expliquons ici le fonctionnement du &lt;strong>protocole d&amp;rsquo;échange de clés ECDH (Elliptic Curve Diffie-Hellman)&lt;/strong>, qui est l&amp;rsquo;application la plus représentative de l&amp;rsquo;ECC. L&amp;rsquo;ECDH est un mécanisme permettant à Alice et Bob de générer et de partager en toute sécurité une clé secrète commune (clé de session) sur un canal de communication vulnérable à l&amp;rsquo;écoute (c&amp;rsquo;est le cœur du handshake TLS).&lt;/p>
&lt;p>&lt;strong>[Paramètres préalables (Paramètres de domaine)]&lt;/strong>
Les deux parties partagent au préalable la courbe elliptique $E$ à utiliser, le nombre premier $p$ et le point de base $G$. (Par exemple NIST P-256 ou secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "Alice"
participant Bob as "Bob"
Note over Alice,Bob: "Paramètres publics : Courbe E, point de base G, premier p"
Alice->>Alice: "Générer la clé privée d_A (entier aléatoire)"
Alice->>Alice: "Calculer la clé publique Q_A = d_A * G"
Bob->>Bob: "Générer la clé privée d_B (entier aléatoire)"
Bob->>Bob: "Calculer la clé publique Q_B = d_B * G"
Alice->>Bob: "Envoyer la clé publique Q_A (en clair)"
Bob->>Alice: "Envoyer la clé publique Q_B (en clair)"
Alice->>Alice: "Calculer le secret partagé S = d_A * Q_B"
Bob->>Bob: "Calculer le secret partagé S = d_B * Q_A"
Note over Alice,Bob: "S = d_A * (d_B * G) = d_B * (d_A * G) = (d_A * d_B) * G"
Note over Alice,Bob: "Les résultats de calcul S des deux parties correspondent parfaitement !"&lt;/div>
&lt;p>Un attaquant (Eve) peut intercepter $G$, $Q_A$ et $Q_B$ circulant sur le canal de communication, mais en raison de la difficulté de l&amp;rsquo;ECDLP, il ne peut pas déduire la clé privée d&amp;rsquo;Alice $d_A$ à partir de $Q_A = d_A \cdot G$. De plus, multiplier $Q_A$ et $Q_B$ ne donne pas la clé partagée $S$, donc un attaquant ne peut pas calculer $S$.&lt;/p>
&lt;hr>
&lt;h2 id="7-pièges-dimplémentation--attaques-par-canaux-auxiliaires-et-contre-mesures">7. Pièges d&amp;rsquo;implémentation : Attaques par canaux auxiliaires et contre-mesures
&lt;/h2>&lt;p>Même avec un algorithme cryptographique théoriquement parfait, des vulnérabilités peuvent apparaître lors du processus d&amp;rsquo;implémentation du programme. C&amp;rsquo;est ce qu&amp;rsquo;on appelle les &lt;strong>&amp;ldquo;attaques par canaux auxiliaires (Side-Channel Attack)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="71-attaque-temporelle-timing-attack">7.1. Attaque temporelle (Timing Attack)
&lt;/h3>&lt;p>Revenons sur l&amp;rsquo;algorithme Double-and-Add mentionné précédemment.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Pseudo-code vulnérable du Double-and-Add
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Infinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">255&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointDoubling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Toujours exécuté
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointAddition&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Exécuté uniquement quand le bit est à 1 !
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Cette implémentation présente un défaut fatal. Comme la Point Addition est exécutée lorsque le bit est &lt;code>1&lt;/code>, le temps de calcul est &lt;strong>légèrement plus long&lt;/strong> que lorsque le bit est &lt;code>0&lt;/code>. De plus, la prédiction de branchement du processeur et le comportement de la mémoire cache changent.
En observant statistiquement cette infime différence de temps de calcul (ou de consommation d&amp;rsquo;énergie) des milliers de fois, un attaquant peut &lt;strong>récupérer complètement la séquence de bits de la clé privée $k$ un par un&lt;/strong>. C&amp;rsquo;est une attaque temporelle.&lt;/p>
&lt;h3 id="72-implémentation-en-temps-constant-constant-time--léchelle-de-montgomery-montgomery-ladder">7.2. Implémentation en temps constant (Constant-Time) : L&amp;rsquo;échelle de Montgomery (Montgomery Ladder)
&lt;/h3>&lt;p>Pour empêcher les attaques temporelles, il est nécessaire d&amp;rsquo;adopter un algorithme dont &lt;strong>la séquence d&amp;rsquo;instructions exécutées et le temps de calcul sont toujours constants (Constant-Time), quelle que soit la valeur des bits de la clé privée&lt;/strong>.&lt;/p>
&lt;p>L&amp;rsquo;exemple le plus représentatif est l&amp;rsquo;&lt;strong>échelle de Montgomery (Montgomery Ladder)&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["Initialisation : R0 = O, R1 = P"] --> LoopStart["Pour chaque bit i (depuis le poids fort)"]
LoopStart --> Cond{"Valeur de k_i ?"}
Cond -->|0| Branch0["R1 = R0 + R1&lt;br>R0 = 2 * R0"]
Cond -->|1| Branch1["R0 = R0 + R1&lt;br>R1 = 2 * R1"]
Branch0 --> LoopEnd["Bit suivant"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"Tous les bits terminés"| End["Fin : R0 est le résultat (kP)"]&lt;/div>
&lt;p>La beauté de l&amp;rsquo;échelle de Montgomery réside dans le fait que, que le bit soit &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, &lt;strong>&amp;ldquo;exactement 1 Point Addition et 1 Point Doubling&amp;rdquo;&lt;/strong> sont toujours exécutés. Cela élimine complètement la dépendance des données sur le temps de calcul.&lt;/p>
&lt;p>Cependant, si le branchement conditionnel (&lt;code>if (k_i == 0)&lt;/code>) lui-même existe, il reste un risque que le temps d&amp;rsquo;exécution fluctue en raison des optimisations du compilateur ou de la prédiction de branchement du processeur. Par conséquent, dans les implémentations réelles en temps constant, les branchements conditionnels (instructions &lt;code>if&lt;/code>) sont éliminés, et un &lt;strong>échange conditionnel utilisant des opérations bit à bit (Conditional Swap)&lt;/strong> est utilisé.&lt;/p>
&lt;hr>
&lt;h2 id="8-implémentation-de-la-cryptographie-sur-les-courbes-elliptiques-en-c">8. Implémentation de la cryptographie sur les courbes elliptiques en C++
&lt;/h2>&lt;p>À partir de là, nous allons traduire la théorie en code C++. Les bibliothèques cryptographiques pratiques (telles que OpenSSL ou libsodium) utilisent des optimisations avancées en assembleur et des systèmes de coordonnées jacobiennes, mais ici, pour approfondir la compréhension mathématique, nous présenterons le squelette d&amp;rsquo;une &lt;strong>implémentation claire en temps constant utilisant des coordonnées affines&lt;/strong>.&lt;/p>
&lt;p>Nous supposerons l&amp;rsquo;utilisation de &lt;code>boost::multiprecision::cpp_int&lt;/code> pour les opérations sur les très grands entiers.&lt;/p>
&lt;h3 id="81-arithmétique-modulaire-et-inverse">8.1. Arithmétique modulaire et inverse
&lt;/h3>&lt;p>Tout d&amp;rsquo;abord, nous définissons des fonctions d&amp;rsquo;aide pour les opérations sur les corps finis. Nous implémentons le calcul de l&amp;rsquo;inverse en utilisant le petit théorème de Fermat.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;boost/multiprecision/cpp_int.hpp&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Exemple avec le premier p et les paramètres de secp256k1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Opération modulo retournant un reste positif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nl">m&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Calcul de l&amp;#39;exponentiation modulaire (x^y mod m)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">exp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">res&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Inverse modulo utilisant le petit théorème de Fermat
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Prémisse que m est premier : n^(m-2) ≡ n^(-1) mod m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="82-représentation-des-points-et-opérations-de-groupe-addition-doublement">8.2. Représentation des points et opérations de groupe (Addition, Doublement)
&lt;/h3>&lt;p>Nous définissons une structure &lt;code>Point&lt;/code> qui gère le point à l&amp;rsquo;infini avec un drapeau, et nous implémentons les formules d&amp;rsquo;addition.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Point&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">bool&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Création d&amp;#39;un point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Création d&amp;#39;un point normal
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Addition de points sur la courbe elliptique (R = P + Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// P + (-P) = Point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">lambda&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Point Doubling (Cas où P = Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (3x^2 + a) / 2y
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Point Addition (Cas où P != Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (y2 - y1) / (x2 - x1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">lambda&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">x3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y3&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="83-implémentation-du-conditional-swap-en-temps-constant">8.3. Implémentation du Conditional Swap en temps constant
&lt;/h3>&lt;p>Lors de l&amp;rsquo;échange du contenu des variables basé sur la valeur du bit de la clé privée, nous effectuons l&amp;rsquo;échange uniquement avec des opérations bit à bit (masque) sans utiliser l&amp;rsquo;instruction &lt;code>if&lt;/code>. Cela garantit que le chemin d&amp;rsquo;exécution reste parfaitement constant.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
Dans une implémentation réelle, une classe d&amp;rsquo;entiers à précision multiple allouée dynamiquement comme &lt;code>cpp_int&lt;/code> ne convient pas au traitement en temps constant. En effet, des informations temporelles fuient en raison des allocations de mémoire et des variations de taille des tableaux. Les bibliothèques pratiques les représentent sous forme de taille fixe (par exemple, un tableau de uint64_t × 4 éléments) et implémentent le traitement des masques au niveau du bit. Voici un exemple conceptuel.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Conditional Swap conceptuel en temps constant (supposant des entiers de taille fixe)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Si le bit est 1, échanger P1 et P2, sinon ne pas échanger
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// bit vaut 0 ou 1. Le masque est tout à 1 (0xFF..) si bit=1, et tout à 0 si bit=0.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (Ici pour l&amp;#39;explication, nous supposons que chaque mot de la classe BigInt de taille fixe est w)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="cm">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t mask = 0 - (uint64_t)bit;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> for (int i = 0; i &amp;lt; NUM_WORDS; i++) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t dummy = mask &amp;amp; (P1.x.words[i] ^ P2.x.words[i]);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P1.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P2.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> // Traiter les coordonnées y et le drapeau isInfinity de la même manière
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// * Un échange parfait en temps constant est difficile avec boost::multiprecision,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// donc nous nous limitons ici à une simulation par branchement pour la compréhension de la logique.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="84-multiplication-scalaire-avec-léchelle-de-montgomery">8.4. Multiplication scalaire avec l&amp;rsquo;échelle de Montgomery
&lt;/h3>&lt;p>En combinant les &lt;code>pointAdd&lt;/code> et &lt;code>cswap&lt;/code> précédents, nous implémentons une multiplication scalaire sécurisée.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Multiplication scalaire k * P (Méthode Montgomery Ladder)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">scalarMultiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Point&lt;/span> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// Point à l&amp;#39;infini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Obtenir la longueur en bits de k (256 bits pour secp256k1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Obtenir la valeur du i-ème bit (0 ou 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bit_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si bit == 1, échanger R0 et R1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Toujours exécuter les mêmes opérations (Point Addition et Point Doubling)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si bit == 1, échanger à nouveau pour restaurer l&amp;#39;état
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Avec cette logique d&amp;rsquo;implémentation, que chaque bit du scalaire $k$ soit &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, les opérations exécutées dans chaque itération de la boucle (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) suivent exactement le même flux. Cela empêche efficacement la fuite d&amp;rsquo;informations secrètes via des différences de timing ou de modèles d&amp;rsquo;accès au cache.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion">9. Conclusion
&lt;/h2>&lt;p>La cryptographie sur les courbes elliptiques (ECC) peut sembler mystérieuse à première vue : &amp;ldquo;Comment une opération géométrique consistant à tracer une droite et refléter son intersection peut-elle devenir une cryptographie ?&amp;rdquo;. Cependant, en la mappant sur le monde discret des corps finis, on peut construire une magnifique fonction à sens unique (problème du logarithme discret), fruit d&amp;rsquo;une fusion miraculeuse entre les mathématiques et la cryptographie.&lt;/p>
&lt;p>Cet article a expliqué les points importants suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Supériorité par rapport à RSA&lt;/strong> : Offre une sécurité forte avec une taille de clé très courte, ce qui est optimal pour l&amp;rsquo;ère moderne du mobile et de l&amp;rsquo;IoT.&lt;/li>
&lt;li>&lt;strong>Fondements de la théorie des groupes et des corps finis&lt;/strong> : Les structures mathématiques sur lesquelles repose l&amp;rsquo;ECC.&lt;/li>
&lt;li>&lt;strong>Formules d&amp;rsquo;addition et de doublement&lt;/strong> : Méthode d&amp;rsquo;implémentation des opérations algébriques de groupe à l&amp;rsquo;aide de l&amp;rsquo;équation de Weierstrass.&lt;/li>
&lt;li>&lt;strong>Menace des attaques par canaux auxiliaires&lt;/strong> : Le fait que les branchements conditionnels dépendants des bits de la clé privée créent une vulnérabilité fatale.&lt;/li>
&lt;li>&lt;strong>Implémentation en temps constant (Constant-Time)&lt;/strong> : Technique de codage en C++ pour homogénéiser le comportement au niveau matériel et prévenir les attaques à l&amp;rsquo;aide du Montgomery Ladder et du Conditional Swap.&lt;/li>
&lt;/ol>
&lt;p>Écrire soi-même une bibliothèque cryptographique fonctionnant en environnement de production est fortement déconseillé (&amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;) car les risques de sécurité sont extrêmement élevés. Cependant, comprendre en profondeur les algorithmes et le contexte mathématique qui fonctionnent en son sein devrait être une arme incroyablement puissante pour les ingénieurs concevant et exploitant des systèmes plus sécurisés et plus performants.&lt;/p>
&lt;p>Dans le prochain article, nous approfondirons le mécanisme de l&amp;rsquo;&lt;strong>ECDSA (Elliptic Curve Digital Signature Algorithm)&lt;/strong>, un algorithme de signature numérique utilisant ces courbes elliptiques, ainsi que les &lt;strong>signatures de Schnorr&lt;/strong> adoptées par Bitcoin.&lt;/p></description></item></channel></rss>