<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mathematics on kenji.blog</title><link>http://kenji.blog/de/tags/mathematics/</link><description>Recent content in Mathematics on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 10:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/mathematics/index.xml" rel="self" type="application/rss+xml"/><item><title>Mathematische Grundlagen der Elliptischen-Kurven-Kryptographie (ECC) und ihre Implementierung in C++</title><link>http://kenji.blog/de/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/de/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 Mathematische Grundlagen der Elliptischen-Kurven-Kryptographie (ECC) und ihre Implementierung in C++" />&lt;h1 id="mathematische-grundlagen-der-elliptischen-kurven-kryptographie-ecc-und-ihre-implementierung-in-c">Mathematische Grundlagen der Elliptischen-Kurven-Kryptographie (ECC) und ihre Implementierung in C++
&lt;/h1>&lt;p>In der modernen Kryptographie spielt die &lt;strong>Elliptische-Kurven-Kryptographie (Elliptic Curve Cryptography: ECC)&lt;/strong> eine äußerst wichtige Rolle. Von unserer täglichen Internetkommunikation (HTTPS/TLS) über die Secure Enclaves von Smartphones, Serverauthentifizierung via SSH, passwortlose Authentifizierung wie FIDO bis hin zu Krypto-Assets wie Bitcoin und Ethereum – man kann ohne Übertreibung sagen, dass die Vertrauensbasis unserer modernen digitalen Gesellschaft durch ECC gestützt wird.&lt;/p>
&lt;p>In diesem Artikel werden wir ausführlich erläutern, wie diese elliptische Kurven-Kryptographie funktioniert. Wir beginnen mit der schönen, aber komplexen mathematischen Theorie dahinter (algebraische Geometrie über endlichen Körpern), gehen dann zur tatsächlichen Implementierung in C++ über und behandeln schließlich sichere Codierungstechniken zur Verhinderung von Seitenkanalangriffen (Timing-Angriffen) – alles in einem überwältigenden Detailreichtum.&lt;/p>
&lt;hr>
&lt;h2 id="1-warum-elliptische-kurven-kryptographie-vergleich-mit-rsa">1. Warum Elliptische-Kurven-Kryptographie? (Vergleich mit RSA)
&lt;/h2>&lt;p>Lange Zeit war &lt;strong>RSA&lt;/strong> das Synonym für Public-Key-Kryptographie. Die Sicherheit von RSA basiert auf der &amp;ldquo;Schwierigkeit der Primfaktorzerlegung riesiger zusammengesetzter Zahlen&amp;rdquo;. Mit der steigenden Rechenleistung von Computern wurde es jedoch notwendig, die Schlüssellänge von RSA (die Bitlänge des Moduls) kontinuierlich zu erhöhen, um die Sicherheit aufrechtzuerhalten. Heutzutage wird eine Schlüssellänge von mindestens 2048 Bit empfohlen, für noch mehr Sicherheit sogar 3072 oder 4096 Bit.&lt;/p>
&lt;p>Im Gegensatz dazu basiert die Elliptische-Kurven-Kryptographie (ECC) auf einer anderen mathematischen Schwierigkeit: dem &lt;strong>&amp;ldquo;Diskreten Logarithmusproblem auf elliptischen Kurven (ECDLP)&amp;rdquo;&lt;/strong>. Bis heute wurde kein effizienter Algorithmus (wie z. B. ein Subexponentialzeit-Algorithmus) zur Lösung des ECDLP gefunden, und selbst die effizientesten bekannten Angriffsmethoden benötigen exponentielle Zeit.&lt;/p>
&lt;p>Aufgrund dieser Eigenschaft hat ECC den entscheidenden Vorteil, &lt;strong>dass es mit sehr kurzen Schlüssellängen die gleiche Sicherheitsstärke wie RSA erreichen kann&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">Sicherheitsstärke (Bit)&lt;/th>
&lt;th style="text-align:center">RSA-Schlüssellänge (Bit)&lt;/th>
&lt;th style="text-align:center">ECC-Schlüssellänge (Bit)&lt;/th>
&lt;th style="text-align:center">Längenverhältnis&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>Wie die obige Tabelle zeigt, benötigt RSA für eine Sicherheitsstärke von 128 Bit (die aktuelle Standardstärke) einen 3072-Bit-Schlüssel, während ECC mit nur 256 Bit auskommt. Dies ermöglicht eine Reduzierung des Rechenaufwands, einen geringeren Speicherverbrauch und die Einsparung von Netzwerkbandbreite. Dadurch ist ECC besonders in ressourcenbeschränkten Umgebungen wie IoT-Geräten und Smartcards überlegen.&lt;/p>
&lt;hr>
&lt;h2 id="2-mathematische-vorbereitung-gruppentheorie-und-endliche-körper">2. Mathematische Vorbereitung: Gruppentheorie und endliche Körper
&lt;/h2>&lt;p>Um die Elliptische-Kurven-Kryptographie wirklich zu verstehen, ist es notwendig, die grundlegenden Konzepte der abstrakten Algebra (Gruppen- und Körpertheorie) zu beherrschen. Hier fassen wir das Vorwissen zur Konstruktion von ECC kurz zusammen.&lt;/p>
&lt;h3 id="21-gruppen-group-und-abelsche-gruppen">2.1. Gruppen (Group) und abelsche Gruppen
&lt;/h3>&lt;p>Eine &lt;strong>Gruppe (Group)&lt;/strong> ist ein Paar $(G, +)$, bestehend aus einer Menge $G$ und einer binären Operation auf dieser Menge (hier als Addition $+$ bezeichnet), das die folgenden vier Axiome erfüllt:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Abgeschlossenheit (Closure)&lt;/strong>: Für beliebige $a, b \in G$ gilt $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>Assoziativgesetz (Associativity)&lt;/strong>: Für beliebige $a, b, c \in G$ gilt $(a + b) + c = a + (b + c)$.&lt;/li>
&lt;li>&lt;strong>Existenz eines neutralen Elements (Identity element)&lt;/strong>: Es existiert ein Element $e \in G$, sodass für jedes $a \in G$ gilt: $a + e = e + a = a$. Bei additiven Gruppen wird dieses neutrale Element meist als $0$ oder $\mathcal{O}$ geschrieben.&lt;/li>
&lt;li>&lt;strong>Existenz inverser Elemente (Inverse element)&lt;/strong>: Zu jedem $a \in G$ existiert ein Element $b \in G$, sodass $a + b = b + a = e$. Dieses $b$ wird als $-a$ bezeichnet.&lt;/li>
&lt;/ol>
&lt;p>Eine Gruppe, in der die Reihenfolge der Operanden das Ergebnis nicht verändert, d. h. die folgende Bedingung erfüllt ist, wird als &lt;strong>abelsche Gruppe (kommutative Gruppe)&lt;/strong> bezeichnet:&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>Kommutativgesetz (Commutativity)&lt;/strong>: Für beliebige $a, b \in G$ gilt $a + b = b + a$.&lt;/li>
&lt;/ol>
&lt;p>Die Menge der Punkte auf einer elliptischen Kurve bildet eine solche &lt;strong>abelsche Gruppe&lt;/strong>, wenn wir eine spezifische Additionsregel definieren.&lt;/p>
&lt;h3 id="22-endliche-körper-finite-field">2.2. Endliche Körper (Finite Field)
&lt;/h3>&lt;p>In der Kryptographietheorie verwenden wir keine Körper mit kontinuierlichen und unendlich vielen Elementen wie die reellen oder komplexen Zahlen, sondern &lt;strong>endliche Körper (Finite Fields)&lt;/strong> oder Galois-Körper (Galois Fields), deren Elementanzahl endlich ist.&lt;/p>
&lt;p>Der grundlegendste endliche Körper ist der &lt;strong>Primkörper $\mathbb{F}_p$&lt;/strong> unter Verwendung einer Primzahl $p$. Dies ist die Menge der ganzen Zahlen $\{0, 1, 2, \dots, p-1\}$ versehen mit den vier Grundrechenarten (Addition, Subtraktion, Multiplikation, Division) modulo $p$ (dem Rest bei Division durch $p$).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Addition&lt;/strong>: $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Subtraktion&lt;/strong>: $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Multiplikation&lt;/strong>: $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Division&lt;/strong>: $a \times b^{-1} \pmod p$ (wobei $b^{-1}$ das multiplikative Inverse von $b$ modulo $p$ ist)&lt;/li>
&lt;/ul>
&lt;p>Die Berechnung des &lt;strong>multiplikativen Inversen (Modular Multiplicative Inverse)&lt;/strong> ist in der kryptographischen Implementierung extrem wichtig. Um ein $b^{-1}$ zu finden, das $b \times b^{-1} \equiv 1 \pmod p$ erfüllt, werden hauptsächlich die folgenden zwei Algorithmen verwendet:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Erweiterter euklidischer Algorithmus (Extended Euclidean Algorithm)&lt;/strong>: Er ist schnell, aber je nach Implementierung ist die Ausführungszeit vom Eingabewert abhängig, was das Risiko von Timing-Angriffen birgt.&lt;/li>
&lt;li>&lt;strong>Kleiner fermatscher Satz (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>: Wenn $p$ eine Primzahl ist und $b \neq 0$, gilt $b^{p-1} \equiv 1 \pmod p$. Teilt man beide Seiten durch $b$, erhält man $b^{p-2} \equiv b^{-1} \pmod p$. Das heißt, durch Berechnung von $b$ hoch $p-2$ erhält man das Inverse. Da modulare Potenzierung leicht in konstanter Zeit (Constant-Time) implementiert werden kann, wird dies bei kryptographischen Implementierungen bevorzugt.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-die-gleichung-und-geometrie-der-elliptischen-kurve">3. Die Gleichung und Geometrie der elliptischen Kurve
&lt;/h2>&lt;h3 id="31-die-weierstraß-normalform">3.1. Die Weierstraß-Normalform
&lt;/h3>&lt;p>Eine &lt;strong>elliptische Kurve (Elliptic Curve)&lt;/strong> ist im Allgemeinen eine ebene Kurve, die durch die folgende Gleichung definiert wird, bekannt als &lt;strong>Weierstraß-Normalform (Weierstrass normal form)&lt;/strong>:&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>Hierbei sind $a$ und $b$ Konstanten. Als Bedingung dafür, dass die Kurve keine Singularitäten (Selbstüberschneidungen oder Spitzen) aufweist (d. h. eine glatte Kurve ist), darf die folgende &lt;strong>Diskriminante (Discriminant) $\Delta$&lt;/strong> nicht null sein:&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>Da Kurven mit Singularitäten die kryptographische Sicherheit beeinträchtigen, werden immer Koeffizienten $a, b$ gewählt, die diese Bedingung erfüllen.&lt;/p>
&lt;h3 id="32-der-punkt-im-unendlichen-point-at-infinity">3.2. Der Punkt im Unendlichen (Point at Infinity)
&lt;/h3>&lt;p>Um die elliptische Kurve mathematisch zu einer vollständigen Gruppe zu machen, führen wir neben den Punkten auf der Ebene einen virtuellen Punkt ein, den &lt;strong>&amp;ldquo;Punkt im Unendlichen&amp;rdquo; (Point at Infinity)&lt;/strong>. Dieser wird mit $\mathcal{O}$ bezeichnet.&lt;/p>
&lt;p>Der Punkt im Unendlichen $\mathcal{O}$ ist definiert als der Punkt, an dem sich alle vertikalen Linien in der unendlichen Ferne schneiden. In der Gruppentheorie fungiert dieser Punkt im Unendlichen $\mathcal{O}$ als &lt;strong>neutrales Element&lt;/strong> (die Null) der Addition.&lt;/p>
&lt;p>Das heißt, für jeden beliebigen Punkt $P$ auf der Kurve gilt:
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>Zudem ist das Inverse $-P$ eines Punktes $P = (x, y)$ definiert als der an der x-Achse gespiegelte Punkt $(x, -y)$. Daher gilt:
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;hr>
&lt;h2 id="4-gruppenoperationen-auf-elliptischen-kurven-punktaddition-und--verdopplung">4. Gruppenoperationen auf elliptischen Kurven (Punktaddition und -verdopplung)
&lt;/h2>&lt;p>Die Grundlage der Elliptischen-Kurven-Kryptographie ist die &lt;strong>&amp;ldquo;Addition&amp;rdquo;&lt;/strong> von Punkten auf der Kurve. Diese unterscheidet sich von der gewöhnlichen Addition von Ganzzahlen und wird basierend auf geometrischen Operationen definiert.&lt;/p>
&lt;h3 id="41-geometrische-addition-tangent-and-chord-method">4.1. Geometrische Addition (Tangent and Chord Method)
&lt;/h3>&lt;p>Das Verfahren, um zwei verschiedene Punkte $P$ und $Q$ auf der Kurve zu addieren, um einen neuen Punkt $R$ ($R = P + Q$) zu finden, ist wie folgt:&lt;/p>
&lt;ol>
&lt;li>Ziehe eine Gerade (Sekante) durch den Punkt $P$ und den Punkt $Q$.&lt;/li>
&lt;li>Diese Gerade schneidet die elliptische Kurve garantiert in einem dritten Punkt (nennen wir ihn $-R$). (※ Gemäß den Sätzen der algebraischen Geometrie)&lt;/li>
&lt;li>Der Punkt, den man erhält, wenn man den Schnittpunkt $-R$ an der x-Achse spiegelt (also das Vorzeichen der y-Koordinate umkehrt), ist der gesuchte Punkt $R$.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["Ziehe eine Gerade durch P(x1, y1) und Q(x2, y2)"] --> Step2["Finde den dritten Schnittpunkt -R mit der Kurve"]
Step2 --> Step3["Spiegele -R an der x-Achse, um R(x3, y3) zu erhalten"]
Step3 -.-> Result["Dies ist R = P + Q"]&lt;/div>
&lt;h3 id="42-punktverdopplung-point-doubling">4.2. Punktverdopplung (Point Doubling)
&lt;/h3>&lt;p>Wenn man denselben Punkt $P$ zu sich selbst addiert ($P + P = 2P$), kann man keine Gerade durch zwei Punkte ziehen. In diesem Fall zieht man &lt;strong>die Tangente an die Kurve im Punkt $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Ziehe die Tangente an die Kurve im Punkt $P$.&lt;/li>
&lt;li>Diese Tangente schneidet die Kurve in einem weiteren Punkt $-R$.&lt;/li>
&lt;li>Der an der x-Achse gespiegelte Schnittpunkt ist der gesuchte Punkt $R = 2P$.&lt;/li>
&lt;/ol>
&lt;h3 id="43-algebraische-berechnungsformeln">4.3. Algebraische Berechnungsformeln
&lt;/h3>&lt;p>Wir übersetzen die geometrischen Operationen in algebraische Formeln, die von einem Computer berechnet werden können.
Alle Operationen werden über dem &lt;strong>endlichen Körper $\mathbb{F}_p$ (modulo $p$)&lt;/strong> durchgeführt.&lt;/p>
&lt;p>Seien die Punkte $P = (x_1, y_1)$ und $Q = (x_2, y_2)$.
Zudem sei der berechnete Ergebnispunkt $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>Die Steigung der Geraden nennen wir $\lambda$ (Lambda).&lt;/p>
&lt;p>&lt;strong>[Fall 1: Wenn $P \neq Q$ (Punktaddition)]&lt;/strong>
Die Steigung $\lambda$ ist die Änderungsrate zwischen den beiden Punkten.
&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>Mit diesem $\lambda$ können $x_3, y_3$ wie folgt berechnet werden:
&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>[Fall 2: Wenn $P = Q$ (Punktverdopplung)]&lt;/strong>
Die Steigung $\lambda$ ist die Steigung der Tangente, die durch Ableitung ermittelt wird. (Wir leiten $y^2 = x^3 + ax + b$ implizit ab)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
Daher gilt:
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>Die Formeln für $x_3, y_3$ haben die gleiche Form wie bei der Addition, aber da $x_2 = x_1$, ergibt sich:
&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]
Diese Formeln enthalten &lt;strong>Divisionen (Berechnung des modularen Inversen)&lt;/strong> wie $(x_2 - x_1)^{-1}$ und $(2y_1)^{-1}$. Da die Berechnung des modularen Inversen sehr rechenintensiv ist, werden in tatsächlichen Implementierungen allgemein projektive Koordinatensysteme wie die &lt;strong>&amp;ldquo;Jacobi-Koordinaten (Jacobian Coordinates)&amp;rdquo;&lt;/strong> verwendet, die die Division verzögern.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-skalarmultiplikation-und-das-diskrete-logarithmusproblem-ecdlp">5. Skalarmultiplikation und das Diskrete Logarithmusproblem (ECDLP)
&lt;/h2>&lt;p>Die rechenintensivste Operation in der Elliptischen-Kurven-Kryptographie, die gleichzeitig den Kern der Sicherheit bildet, ist die &lt;strong>Skalarmultiplikation (Scalar Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="51-was-ist-skalarmultiplikation">5.1. Was ist Skalarmultiplikation?
&lt;/h3>&lt;p>Die Operation, einen Punkt $P$ $k$-mal zu addieren, wird als Skalarmultiplikation bezeichnet und als $kP$ geschrieben.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k\text{ Mal}} $$
&lt;p>Hierbei ist $k$ eine sehr große Ganzzahl (zum Beispiel eine 256-Bit-Ganzzahl).&lt;/p>
&lt;h3 id="52-diskretes-logarithmusproblem-auf-elliptischen-kurven-ecdlp">5.2. Diskretes Logarithmusproblem auf elliptischen Kurven (ECDLP)
&lt;/h3>&lt;p>Die Sicherheit der Elliptischen-Kurven-Kryptographie beruht auf der Schwierigkeit des folgenden Problems:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Diskretes Logarithmusproblem auf elliptischen Kurven (Elliptic Curve Discrete Logarithm Problem: ECDLP)&lt;/strong>
Gegeben sei ein bekannter Punkt $P$ (Basispunkt) und ein berechneter Punkt $Q$. Finde den Skalar $k$, der $Q = kP$ erfüllt.&lt;/p>
&lt;/blockquote>
&lt;p>Es ist mit dem unten beschriebenen Algorithmus einfach (in polynomieller Zeit machbar), $Q$ aus $k$ und $P$ zu berechnen (Vorwärtsrichtung), aber es ist praktisch unmöglich, $k$ aus $P$ und $Q$ zurückzurechnen (Rückwärtsrichtung), da es außer Brute-Force-Suchen keine effiziente Lösungsmethode gibt (Einwegfunktion).
In kryptographischen Protokollen entspricht &lt;strong>$k$ dem &amp;ldquo;privaten Schlüssel&amp;rdquo; und $Q$ dem &amp;ldquo;öffentlichen Schlüssel&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-double-and-add-algorithmus">5.3. Double-and-Add-Algorithmus
&lt;/h3>&lt;p>Wenn $k$ eine riesige Zahl ist (z. B. $2^{256}$), würde die naive Addition von $P$ um $k$-mal das Ende der Lebensdauer des Universums überdauern. Daher wird die &lt;strong>Double-and-Add-Methode (binäre Methode)&lt;/strong> verwendet, um die Skalarmultiplikation schnell durchzuführen.&lt;/p>
&lt;p>Dies ist die elliptische Kurvenversion der &amp;ldquo;binären Exponentiation&amp;rdquo;, mit der die Potenzierung von Ganzzahlen schnell berechnet wird. Der Skalar $k$ wird binär dargestellt und vom höchstwertigen Bit an verarbeitet.&lt;/p>
&lt;ol>
&lt;li>Initialisiere den Punkt $R$, der das Ergebnis hält, mit $\mathcal{O}$.&lt;/li>
&lt;li>Wiederhole für jedes Bit von $k$, vom höchstwertigen bis zum niederwertigsten:
&lt;ul>
&lt;li>Verdopple $R$ (Point Doubling: $R = 2R$)&lt;/li>
&lt;li>Wenn das aktuelle Bit &lt;code>1&lt;/code> ist, addiere $P$ zu $R$ (Point Addition: $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Durch diesen Algorithmus wird der Rechenaufwand drastisch von $O(k)$ auf $O(\log_2 k)$ reduziert, was die Berechnung in realistischer Zeit (im Millisekundenbereich) ermöglicht.&lt;/p>
&lt;hr>
&lt;h2 id="6-elliptic-curve-diffie-hellman-ecdh-schlüsselaustausch">6. Elliptic Curve Diffie-Hellman (ECDH) Schlüsselaustausch
&lt;/h2>&lt;p>Hier erklären wir den Mechanismus des &lt;strong>ECDH (Elliptic Curve Diffie-Hellman) Schlüsselaustauschprotokolls&lt;/strong>, welches das repräsentativste Anwendungsbeispiel für ECC ist. ECDH ist ein Mechanismus, mit dem Alice und Bob sicher einen gemeinsamen geheimen Schlüssel (Sitzungsschlüssel) über einen abhörbaren Kommunikationskanal generieren und austauschen können (dies ist der Kern des TLS-Handshakes).&lt;/p>
&lt;p>&lt;strong>[Vorab-Parameter (Domain Parameters)]&lt;/strong>
Beide Parteien haben sich im Voraus auf die zu verwendende elliptische Kurve $E$, die Primzahl $p$ und den Basispunkt $G$ geeinigt. (Beispiele sind NIST P-256 oder secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "Alice"
participant Bob as "Bob"
Note over Alice,Bob: "Öffentliche Parameter: Kurve E, Basispunkt G, Primzahl p"
Alice->>Alice: "Generiere privaten Schlüssel d_A (zufällige Ganzzahl)"
Alice->>Alice: "Berechne öffentlichen Schlüssel Q_A = d_A * G"
Bob->>Bob: "Generiere privaten Schlüssel d_B (zufällige Ganzzahl)"
Bob->>Bob: "Berechne öffentlichen Schlüssel Q_B = d_B * G"
Alice->>Bob: "Sende öffentlichen Schlüssel Q_A (Klartext)"
Bob->>Alice: "Sende öffentlichen Schlüssel Q_B (Klartext)"
Alice->>Alice: "Berechne gemeinsames Geheimnis S = d_A * Q_B"
Bob->>Bob: "Berechne gemeinsames Geheimnis 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: "Die berechneten Ergebnisse S von beiden stimmen exakt überein!"&lt;/div>
&lt;p>Ein Lauscher (Eve) kann $G$, $Q_A$ und $Q_B$, die über den Kommunikationsweg fließen, abfangen, aber aufgrund der Schwierigkeit des ECDLP kann er Alices privaten Schlüssel $d_A$ nicht aus $Q_A = d_A \cdot G$ ermitteln. Außerdem ergibt die Multiplikation von $Q_A$ und $Q_B$ nicht den gemeinsamen Schlüssel $S$, sodass der Lauscher $S$ nicht berechnen kann.&lt;/p>
&lt;hr>
&lt;h2 id="7-fallstricke-bei-der-implementierung-seitenkanalangriffe-und-gegenmaßnahmen">7. Fallstricke bei der Implementierung: Seitenkanalangriffe und Gegenmaßnahmen
&lt;/h2>&lt;p>Selbst ein theoretisch perfekter kryptographischer Algorithmus kann im Prozess seiner Implementierung als Programm Schwachstellen aufweisen. Das sind die sogenannten &lt;strong>&amp;ldquo;Seitenkanalangriffe&amp;rdquo; (Side-Channel Attacks)&lt;/strong>.&lt;/p>
&lt;h3 id="71-timing-angriffe-timing-attack">7.1. Timing-Angriffe (Timing Attack)
&lt;/h3>&lt;p>Schauen wir uns den zuvor erwähnten Double-and-Add-Algorithmus noch einmal an.&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">// Pseudocode eines anfälligen 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">// Wird immer ausgeführt
&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">// Wird nur ausgeführt, wenn das Bit 1 ist!
&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>Diese Implementierung hat einen fatalen Fehler. Da Point Addition ausgeführt wird, wenn das Bit &lt;code>1&lt;/code> ist, ist &lt;strong>die Berechnungszeit geringfügig länger&lt;/strong>, als wenn das Bit &lt;code>0&lt;/code> ist. Darüber hinaus ändern sich auch die Sprungvorhersage (Branch Prediction) des Prozessors und das Verhalten des Cache-Speichers.
Indem ein Angreifer diesen winzigen Unterschied in der Berechnungszeit (oder dem Stromverbrauch) tausendfach statistisch beobachtet, &lt;strong>kann er die Bitfolge des privaten Schlüssels $k$ Bit für Bit vollständig rekonstruieren&lt;/strong>. Das ist ein Timing-Angriff.&lt;/p>
&lt;h3 id="72-constant-time-implementierung-montgomery-ladder">7.2. Constant-Time-Implementierung: Montgomery Ladder
&lt;/h3>&lt;p>Um Timing-Angriffe zu verhindern, muss man einen Algorithmus wählen, bei dem &lt;strong>die Abfolge der ausgeführten Befehle und die Berechnungszeit unabhängig vom Bitwert des privaten Schlüssels immer konstant (Constant-Time) sind&lt;/strong>.&lt;/p>
&lt;p>Das typischste Beispiel dafür ist die &lt;strong>Montgomery Ladder (Montgomery-Leiter)&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["Initialisierung: R0 = O, R1 = P"] --> LoopStart["Für jedes Bit i (vom höchstwertigen)"]
LoopStart --> Cond{"Wert von 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["Zum nächsten Bit"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"Alle Bits abgeschlossen"| End["Ende: R0 ist das Ergebnis (kP)"]&lt;/div>
&lt;p>Das Schöne an der Montgomery Ladder ist, dass unabhängig davon, ob das Bit &lt;code>0&lt;/code> oder &lt;code>1&lt;/code> ist, &lt;strong>&amp;ldquo;immer genau eine Point Addition und eine Point Doubling&amp;rdquo;&lt;/strong> ausgeführt werden. Dadurch wird die Datenabhängigkeit der Berechnungszeit vollständig eliminiert.&lt;/p>
&lt;p>Wenn jedoch die Verzweigung (&lt;code>if (k_i == 0)&lt;/code>) selbst vorhanden ist, bleibt das Risiko bestehen, dass die Ausführungszeit durch Compileroptimierungen oder die Sprungvorhersage der CPU schwankt. Aus diesem Grund werden in tatsächlichen Constant-Time-Implementierungen bedingte Verzweigungen (&lt;code>if&lt;/code>-Anweisungen) vermieden und stattdessen &lt;strong>bedingtes Vertauschen (Conditional Swap) mit bitweisen Operationen&lt;/strong> verwendet.&lt;/p>
&lt;hr>
&lt;h2 id="8-implementierung-der-elliptischen-kurven-kryptographie-in-c">8. Implementierung der Elliptischen-Kurven-Kryptographie in C++
&lt;/h2>&lt;p>Von nun an werden wir die Theorie in C++-Code umsetzen. Praktische Krypto-Bibliotheken (wie OpenSSL oder libsodium) verwenden hochentwickelte Assembler-Optimierungen und Jacobi-Koordinaten, aber um das mathematische Verständnis zu vertiefen, zeigen wir hier das Gerüst einer &lt;strong>leicht verständlichen Constant-Time-Implementierung mit affinen Koordinaten&lt;/strong>.&lt;/p>
&lt;p>Wir gehen davon aus, dass wir &lt;code>boost::multiprecision::cpp_int&lt;/code> für die Berechnungen mit großen Zahlen verwenden.&lt;/p>
&lt;h3 id="81-modulo-arithmetik-und-inversen">8.1. Modulo-Arithmetik und Inversen
&lt;/h3>&lt;p>Zunächst definieren wir Hilfsfunktionen für Operationen auf endlichen Körpern. Wir implementieren die Inversen-Berechnung mit dem kleinen fermatschen Satz.&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">// Beispiel: Parameter und Primzahl p für 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">// Modulo-Operation, die einen positiven Rest zurückgibt
&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">// Modulare Exponentiation (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">// Modulares Inverses mit dem kleinen fermatschen Satz
&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">// Annahme, dass m eine Primzahl ist: 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-darstellung-von-punkten-und-gruppenoperationen-additionverdopplung">8.2. Darstellung von Punkten und Gruppenoperationen (Addition/Verdopplung)
&lt;/h3>&lt;p>Wir definieren eine &lt;code>Point&lt;/code>-Struktur, die den Punkt im Unendlichen durch ein Flag verwaltet, und implementieren die Additionsformeln.&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">// Erzeugung des Punktes im Unendlichen
&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">// Erzeugung eines normalen Punktes
&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">// Punktaddition auf der elliptischen Kurve (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) = Punkt im Unendlichen
&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 (Wenn 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 (Wenn 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-implementierung-des-constant-time-conditional-swap">8.3. Implementierung des Constant-Time Conditional Swap
&lt;/h3>&lt;p>Wenn der Inhalt von Variablen basierend auf dem Bitwert des privaten Schlüssels vertauscht wird, erfolgt das Vertauschen ausschließlich durch Bitoperationen (Maskierung) ohne die Verwendung von &lt;code>if&lt;/code>-Anweisungen. Dadurch wird der Ausführungspfad völlig konstant.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
In der Praxis sind Klassen für Ganzzahlen mit mehrfacher Genauigkeit, die dynamisch allokiert werden (wie &lt;code>cpp_int&lt;/code>), nicht für Constant-Time-Verarbeitung geeignet. Das liegt daran, dass durch Speicherzuweisung und sich ändernde Array-Größen Timing-Informationen durchsickern. In praktischen Bibliotheken werden stattdessen feste Längen (z. B. ein Array mit 4 Elementen von uint64_t) verwendet, und Maskierungsoperationen auf Bitebene implementiert. Das Folgende ist ein konzeptionelles Beispiel.&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">// Konzeptioneller Constant-Time Swap (ausgehend von Ganzzahlen fester Länge)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Wenn das Bit 1 ist, tausche P1 und P2; wenn es 0 ist, nicht.
&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 ist 0 oder 1. Die Maske ist alle Bits 1 (0xFF..), wenn bit=1, und alle Bits 0, wenn 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">// (Hier wird zur Erklärung angenommen, dass w jedes Wort der BigInt-Klasse fester Länge ist)
&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"> // Die y-Koordinate und das isInfinity-Flag werden auf ähnliche Weise verarbeitet
&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">// ※ Ein vollständiger Constant-Time-Swap mit boost::multiprecision ist schwierig,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// daher beschränken wir uns hier auf die Simulation durch Verzweigung zum Verständnis der Logik.
&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-skalarmultiplikation-durch-montgomery-ladder">8.4. Skalarmultiplikation durch Montgomery Ladder
&lt;/h3>&lt;p>Wir kombinieren das zuvor beschriebene &lt;code>pointAdd&lt;/code> und &lt;code>cswap&lt;/code>, um eine sichere Skalarmultiplikation zu implementieren.&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">// Skalarmultiplikation k * P (Montgomery Ladder Methode)
&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">// Punkt im Unendlichen
&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">// Hole die Bitlänge von k (256 Bit für 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">// Hole den Wert des i-ten Bits (0 oder 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">// Wenn bit == 1, tausche R0 und 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">// Führe immer die gleichen Operationen aus (Point Addition und 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">// Wenn bit == 1 war, tausche erneut, um den Zustand wiederherzustellen
&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>Durch diese Implementierungslogik wird – unabhängig davon, ob jedes Bit des Skalars $k$ eine &lt;code>0&lt;/code> oder &lt;code>1&lt;/code> ist – der in jeder Schleifeniteration ausgeführte Ablauf (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) völlig identisch. Dies verhindert effektiv das Durchsickern von Geheiminformationen durch Timing- oder Cache-Zugriffsmusterunterschiede.&lt;/p>
&lt;hr>
&lt;h2 id="9-zusammenfassung">9. Zusammenfassung
&lt;/h2>&lt;p>Die Elliptische-Kurven-Kryptographie (ECC) mag auf den ersten Blick seltsam erscheinen: &amp;ldquo;Warum wird aus einer geometrischen Operation wie dem Ziehen einer Gerade und dem Spiegeln eines Schnittpunkts eine Kryptographie?&amp;rdquo; Wenn man diese Operationen jedoch auf die diskrete Welt endlicher Körper abbildet, entsteht als Produkt der wundersamen Verschmelzung von Mathematik und Kryptographie eine hervorragende Einwegfunktion (das Diskrete Logarithmusproblem).&lt;/p>
&lt;p>Dieser Artikel hat die folgenden wichtigen Punkte behandelt:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Vorteile gegenüber RSA&lt;/strong>: Es bietet starke Sicherheit mit sehr kurzen Schlüssellängen und ist ideal für das moderne Mobile- und IoT-Zeitalter.&lt;/li>
&lt;li>&lt;strong>Grundlagen der Gruppentheorie und endlicher Körper&lt;/strong>: Die inneren mathematischen Strukturen, die das Fundament von ECC bilden.&lt;/li>
&lt;li>&lt;strong>Formeln für Addition und Verdopplung&lt;/strong>: Wie algebraische Gruppenoperationen mit der Weierstraß-Gleichung implementiert werden.&lt;/li>
&lt;li>&lt;strong>Bedrohung durch Seitenkanalangriffe&lt;/strong>: Wie bedingte Verzweigungen, die von den Bits eines privaten Schlüssels abhängen, fatale Schwachstellen schaffen.&lt;/li>
&lt;li>&lt;strong>Constant-Time-Implementierung&lt;/strong>: C++-Codierungstechniken, die Montgomery Ladder und Conditional Swap verwenden, um das Verhalten auf Hardwareebene zu homogenisieren und Angriffe zu verhindern.&lt;/li>
&lt;/ol>
&lt;p>In einer Produktionsumgebung eine eigene Krypto-Bibliothek zu schreiben, birgt ein extrem hohes Sicherheitsrisiko und wird daher nicht empfohlen (&amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;). Die tiefgreifende Kenntnis der intern ablaufenden Algorithmen und mathematischen Hintergründe wird jedoch zu einer unschätzbaren und mächtigen Waffe für Ingenieure, die sicherere und leistungsfähigere Systeme entwerfen und betreiben wollen.&lt;/p>
&lt;p>Im nächsten Artikel werden wir noch tiefer auf den &lt;strong>ECDSA (Elliptic Curve Digital Signature Algorithm)&lt;/strong>, einen digitalen Signaturalgorithmus auf Basis elliptischer Kurven, sowie auf die in Bitcoin verwendeten &lt;strong>Schnorr-Signaturen&lt;/strong> eingehen.&lt;/p></description></item></channel></rss>