<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cryptography on kenji.blog</title><link>http://kenji.blog/de/tags/cryptography/</link><description>Recent content in Cryptography on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 16:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/cryptography/index.xml" rel="self" type="application/rss+xml"/><item><title>Die Riemannsche Vermutung und die Verteilung der Primzahlen: Die tiefe Verbindung zur modernen Kryptographie</title><link>http://kenji.blog/de/p/riemann-hypothesis-prime-distribution-cryptography/</link><pubDate>Fri, 11 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/de/p/riemann-hypothesis-prime-distribution-cryptography/</guid><description>&lt;img src="http://kenji.blog/p/riemann-hypothesis-prime-distribution-cryptography/img/eyecatch.jpg" alt="Featured image of post Die Riemannsche Vermutung und die Verteilung der Primzahlen: Die tiefe Verbindung zur modernen Kryptographie" />&lt;h1 id="1-einleitung-das-geheimnis-des-universums-der-primzahlen-und-die-riemannsche-vermutung">1. Einleitung: Das Geheimnis des Universums der Primzahlen und die Riemannsche Vermutung
&lt;/h1>&lt;p>&amp;ldquo;Primzahlen&amp;rdquo; (Prime Numbers) sind natürliche Zahlen, die nur durch 1 und sich selbst teilbar sind, und werden auch als die &amp;ldquo;Atome&amp;rdquo; der Mathematik bezeichnet. Die Folge 2, 3, 5, 7, 11, 13&amp;hellip; scheint auf den ersten Blick unordentlich und zufällig aufzutreten. Seit der antike griechische Mathematiker Euklid bewiesen hat, dass &amp;ldquo;es unendlich viele Primzahlen gibt&amp;rdquo;, haben unzählige Mathematiker versucht, die verborgenen Gesetzmäßigkeiten in dieser Anordnung von Primzahlen zu entschlüsseln.&lt;/p>
&lt;p>Am nächsten an dieses Rätsel der Primzahlen kam die 1859 von dem deutschen Mathematiker Bernhard Riemann aufgestellte &lt;strong>&amp;ldquo;Riemannsche Vermutung&amp;rdquo; (Riemann Hypothesis)&lt;/strong> heran. Die Riemannsche Vermutung ist eines der wichtigsten und ungelösten Probleme der modernen Mathematik und als eines der Millennium-Probleme des Clay Mathematics Institute mit einem Preisgeld von einer Million Dollar dotiert.&lt;/p>
&lt;p>Auf den ersten Blick mag ein Problem der reinen Mathematik über die Verteilung von Primzahlen nichts mit unserem Alltag zu tun haben. Die Sicherheit des Internets, das die Infrastruktur der modernen Gesellschaft stützt, insbesondere &lt;strong>moderne Verschlüsselungstechnologien wie die RSA-Kryptographie und die Elliptische-Kurven-Kryptographie (ECC)&lt;/strong>, hängt jedoch stark von den Eigenschaften riesiger Primzahlen ab.&lt;/p>
&lt;p>In diesem Artikel begeben wir uns auf eine mathematische Reise von der Verteilung der Primzahlen über den Primzahlsatz und die Riemannsche Zeta-Funktion bis hin zum Kern der Riemannschen Vermutung. Wir werden extrem detailliert und tiefgreifend erklären, wie all dies mit der modernen Kryptographie verbunden ist und was mit der Welt passieren würde, wenn die Riemannsche Vermutung bewiesen werden sollte.&lt;/p>
&lt;hr>
&lt;h1 id="2-der-primzahlsatz-und-die-verteilung-der-primzahlen-die-entdeckung-von-gauss">2. Der Primzahlsatz und die Verteilung der Primzahlen: Die Entdeckung von Gauss
&lt;/h1>&lt;p>Um zu verstehen, wie Primzahlen verteilt sind, betrachteten Mathematiker die &lt;strong>Primzahlzählfunktion (Prime-counting function)&lt;/strong> $\pi(x)$, die angibt, &amp;ldquo;wie viele Primzahlen kleiner oder gleich einer bestimmten Zahl $x$ existieren&amp;rdquo;.&lt;/p>
&lt;p>Zum Beispiel:&lt;/p>
&lt;ul>
&lt;li>$\pi(10) = 4$ (2, 3, 5, 7)&lt;/li>
&lt;li>$\pi(100) = 25$&lt;/li>
&lt;li>$\pi(1000) = 168$&lt;/li>
&lt;/ul>
&lt;p>Der 15-jährige geniale Mathematiker Carl Friedrich Gauss berechnete umfangreiche Primzahltabellen und fand heraus, dass die Häufigkeit des Auftretens von Primzahlen umgekehrt proportional zum natürlichen Logarithmus $\ln x$ abnimmt. Das heißt, er vermutete, dass die Wahrscheinlichkeit, eine Primzahl in der Nähe einer bestimmten Zahl $x$ zu finden, etwa $\frac{1}{\ln x}$ beträgt.&lt;/p>
&lt;p>Dies wird mit Hilfe eines Integrals als &lt;strong>Integrallogarithmus (Logarithmic integral)&lt;/strong> $\text{Li}(x)$ ausgedrückt:&lt;/p>
$$ \text{Li}(x) = \int_{2}^{x} \frac{dt}{\ln t} $$
&lt;p>Die Vermutung von Gauss wurde später 1896 von Jacques Hadamard und Charles-Jean de La Vallée Poussin unabhängig voneinander bewiesen und als &lt;strong>Primzahlsatz (Prime Number Theorem, PNT)&lt;/strong> etabliert.&lt;/p>
$$ \lim_{x \to \infty} \frac{\pi(x)}{\text{Li}(x)} = 1 $$
&lt;p>Oder näherungsweise wie folgt ausgedrückt:&lt;/p>
$$ \pi(x) \sim \frac{x}{\ln x} $$
&lt;p>Durch diesen Satz wurde klar, dass Primzahlen makroskopisch betrachtet eine sehr glatte und vorhersehbare Verteilung aufweisen. Mikroskopisch betrachtet gibt es jedoch immer einen &amp;ldquo;Fehler&amp;rdquo; oder eine &amp;ldquo;Schwankung&amp;rdquo; zwischen $\pi(x)$ und $\text{Li}(x)$. Die wahre Natur dieser Schwankung ist das größte Rätsel, das die Riemannsche Vermutung zu lösen versucht.&lt;/p>
&lt;hr>
&lt;h1 id="3-die-riemannsche-zeta-funktion-und-das-euler-produkt">3. Die Riemannsche Zeta-Funktion und das Euler-Produkt
&lt;/h1>&lt;p>Die stärkste Waffe bei der Analyse der Verteilung von Primzahlen ist die &lt;strong>Riemannsche Zeta-Funktion (Riemann Zeta Function)&lt;/strong>. Ursprünglich war es eine unendliche Reihe, die von Leonhard Euler für reelle Zahlen $s > 1$ definiert wurde.&lt;/p>
$$ \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s} = 1 + \frac{1}{2^s} + \frac{1}{3^s} + \frac{1}{4^s} + \dots $$
&lt;p>Eine der größten Errungenschaften Eulers war der Beweis, dass diese unendliche Reihe als unendliches Produkt über alle Primzahlen $p$ dargestellt werden kann. Dies ist das &lt;strong>Euler-Produkt (Euler Product Formula)&lt;/strong>.&lt;/p>
$$ \zeta(s) = \prod_{p \text{ prime}} \frac{1}{1 - p^{-s}} = \left( \frac{1}{1 - 2^{-s}} \right) \left( \frac{1}{1 - 3^{-s}} \right) \left( \frac{1}{1 - 5^{-s}} \right) \dots $$
&lt;p>Ein intuitives Verständnis des Beweises ist, dass wenn man jeden Term auf der rechten Seite als geometrische Reihe entwickelt und diese miteinander multipliziert, aufgrund des Fundamentalsatzes der Arithmetik (jede natürliche Zahl kann eindeutig als Produkt von Primzahlen dargestellt werden) die Summe der Kehrwerte der natürlichen Zahlen auf der linken Seite vollständig rekonstruiert wird.&lt;/p>
&lt;p>&lt;strong>Diese einzige Formel wurde zur Brücke zwischen der Analysis (unendliche Reihen, stetige Funktionen) und der Zahlentheorie (Primzahlen, diskrete Zahlen).&lt;/strong> Die Untersuchung der Zeta-Funktion ist gleichbedeutend mit der Untersuchung der Verteilung der Primzahlen.&lt;/p>
&lt;hr>
&lt;h1 id="4-analytische-fortsetzung-und-die-erweiterung-auf-die-komplexe-zahlenebene">4. Analytische Fortsetzung und die Erweiterung auf die komplexe Zahlenebene
&lt;/h1>&lt;p>Riemanns Genialität lag darin, dass er die Variable $s$ von $\zeta(s)$, die Euler nur für reelle Zahlen betrachtete, auf &lt;strong>komplexe Zahlen $s = \sigma + it$ ($\sigma$ ist der Realteil, $t$ ist der Imaginärteil)&lt;/strong> erweiterte.&lt;/p>
&lt;p>Die ursprüngliche unendliche Reihe konvergiert nur für $\sigma > 1$, aber Riemann nutzte eine Methode namens &amp;ldquo;analytische Fortsetzung (Analytic Continuation)&amp;rdquo;, um die Definition so zu erweitern, dass $\zeta(s)$ auf der gesamten komplexen Zahlenebene, mit Ausnahme des Pols bei $s = 1$, sinnvoll ist.&lt;/p>
&lt;p>Er leitete außerdem eine wunderschöne Funktionalgleichung (Functional equation) ab, die die Zeta-Funktion erfüllt.&lt;/p>
$$ \zeta(s) = 2^s \pi^{s-1} \sin\left(\frac{\pi s}{2}\right) \Gamma(1-s) \zeta(1-s) $$
&lt;p>Hierbei ist $\Gamma(x)$ die Gamma-Funktion. Durch diese Gleichung können wir die Eigenschaften der linken Halbebene aus den Eigenschaften der rechten Halbebene ableiten.&lt;/p>
&lt;h3 id="nullstellen-zeros-of-the-zeta-function">Nullstellen (Zeros of the Zeta Function)
&lt;/h3>&lt;p>Komplexe Zahlen $s$, für die der Wert der Zeta-Funktion 0 wird, nennt man &amp;ldquo;Nullstellen&amp;rdquo;.
Aus der Funktionalgleichung ergibt sich, dass für negative gerade Zahlen $s$ ($-2, -4, -6, \dots$) $\sin(\pi s / 2)$ zu 0 wird, also $\zeta(s) = 0$. Diese werden &lt;strong>triviale Nullstellen (Trivial zeros)&lt;/strong> genannt.&lt;/p>
&lt;p>Was jedoch für die Verteilung der Primzahlen wichtig ist, sind die anderen Nullstellen, nämlich die &lt;strong>nicht-trivialen Nullstellen (Non-trivial zeros)&lt;/strong>, die im &amp;ldquo;kritischen Streifen (Critical strip)&amp;rdquo; von $0 \le \sigma \le 1$ liegen.&lt;/p>
&lt;hr>
&lt;h1 id="5-der-kern-der-riemannschen-vermutung-und-die-explizite-formel">5. Der Kern der Riemannschen Vermutung und die explizite Formel
&lt;/h1>&lt;p>Riemann berechnete eine kleine Anzahl von Nullstellen und stellte eine erstaunliche Vermutung auf. Dies ist die &lt;strong>Riemannsche Vermutung&lt;/strong>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Riemannsche Vermutung (Riemann Hypothesis)&lt;/strong>
Alle nicht-trivialen Nullstellen der Riemannschen Zeta-Funktion $\zeta(s)$ liegen auf der Geraden, deren Realteil $1/2$ ist ($\text{Re}(s) = 1/2$).&lt;/p>
&lt;/blockquote>
&lt;p>Diese Gerade, deren Realteil 1/2 ist, wird als &amp;ldquo;kritische Gerade (Critical line)&amp;rdquo; bezeichnet.&lt;/p>
&lt;div class="mermaid">graph TD
A["Riemannsche Zeta-Funktion ζ(s)"] --> B["Erweiterung auf die komplexe Ebene durch analytische Fortsetzung"]
B --> C["Triviale Nullstellen (s = -2, -4, -6 ...)"]
B --> D["Nicht-triviale Nullstellen (0 &lt;= Re(s) &lt;= 1)"]
D --> E["Riemannsche Vermutung"]
E --> F["Alle nicht-trivialen Nullstellen liegen auf Re(s) = 1/2"]
F --> G["Zum Beweis des Grenzwerts des Fehlerterms in der Primzahlverteilung"]&lt;/div>
&lt;p>Warum ist die Riemannsche Vermutung so wichtig? Weil die Nullstellen der Zeta-Funktion die Verteilung der Primzahlen &lt;strong>vollständig&lt;/strong> bestimmen.&lt;/p>
&lt;p>Riemann und der spätere Mathematiker von Mangoldt leiteten eine &amp;ldquo;explizite Formel (Explicit formula)&amp;rdquo; ab, die die Verteilung der Primzahlen genau beschreibt. Unter Verwendung der Tschebyschow-Funktion $\psi(x)$ lässt sie sich wie folgt ausdrücken:&lt;/p>
$$ \psi(x) = x - \sum_{\rho} \frac{x^\rho}{\rho} - \ln(2\pi) - \frac{1}{2}\ln(1 - x^{-2}) $$
&lt;p>Hierbei ist $\rho$ die Summe über alle nicht-trivialen Nullstellen der Zeta-Funktion.
Der Hauptterm ist $x$ (der dem Primzahlsatz entspricht), und durch Addition und Subtraktion von wellenartigen Termen, die von den Nullstellen $\rho$ abhängen, wird die genaue treppenförmige Verteilung der Primzahlen wiederhergestellt. Man kann sagen, dass die nicht-trivialen Nullstellen die &amp;ldquo;Frequenzen (Wellen)&amp;rdquo; der Primzahlverteilung darstellen.&lt;/p>
&lt;p>Wenn die Riemannsche Vermutung wahr ist und der Realteil aller nicht-trivialen Nullstellen $\rho$ genau $1/2$ beträgt, dann wird der Fehlerterm des Primzahlsatzes theoretisch auf den kleinstmöglichen Bereich beschränkt sein.&lt;/p>
$$ |\pi(x) - \text{Li}(x)| \le \frac{1}{8\pi} \sqrt{x} \ln x \quad \text{for} \quad x \ge 2657 $$
&lt;p>Das bedeutet: &lt;strong>Wenn die Riemannsche Vermutung wahr ist, wird bewiesen sein, dass Primzahlen auf die &amp;ldquo;regelmäßigste und schönste&amp;rdquo; Weise verteilt sind, die wir uns vorstellen können.&lt;/strong>&lt;/p>
&lt;hr>
&lt;h1 id="6-die-untrennbare-beziehung-zwischen-der-modernen-kryptographie-und-primzahlen">6. Die untrennbare Beziehung zwischen der modernen Kryptographie und Primzahlen
&lt;/h1>&lt;p>Bisher befanden wir uns in der Welt der tiefgründigen reinen Mathematik, aber diese Eigenschaften von Primzahlen stützen die moderne digitale Gesellschaft grundlegend. Der repräsentativste Vertreter dafür ist die Public-Key-Kryptographie wie die &lt;strong>RSA-Kryptographie&lt;/strong>.&lt;/p>
&lt;p>Die Sicherheit jeglicher Kommunikation, von Kreditkartenzahlungen im Internet über das Senden von Passwörtern bis hin zu digitalen Signaturen der Blockchain, hängt von &amp;ldquo;Primzahlen&amp;rdquo; ab.&lt;/p>
&lt;h3 id="funktionsweise-der-rsa-kryptographie">Funktionsweise der RSA-Kryptographie
&lt;/h3>&lt;p>Die Sicherheit der RSA-Kryptographie beruht auf der mathematischen Tatsache, dass &amp;ldquo;die Primfaktorzerlegung großer zusammengesetzter Zahlen sehr schwierig ist&amp;rdquo; (Primfaktorzerlegungsproblem).&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Schlüsselerzeugung (Key generation)&lt;/strong>:
Zwei riesige Primzahlen $p$ und $q$ (z.B. jeweils 2048 Bit) werden zufällig ausgewählt.
Sie werden miteinander multipliziert, um $N = p \times q$ zu berechnen. Dieses $N$ wird Teil des öffentlichen Schlüssels.
Unter Verwendung der Eulerschen Phi-Funktion $\phi(N) = (p-1)(q-1)$ wird der private Schlüssel $d$ generiert.&lt;/p>
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Verschlüsselung und Entschlüsselung&lt;/strong>:
Der Klartext $M$ wird mit dem öffentlichen Schlüssel $e, N$ in einen Geheimtext $C$ umgewandelt.
&lt;/p>
$$ C \equiv M^e \pmod{N} $$
&lt;p>
Nur derjenige mit dem privaten Schlüssel $d$ kann ihn entschlüsseln.
&lt;/p>
$$ M \equiv C^d \pmod{N} $$
&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["Klartext (Plaintext)"] --> B["Verschlüsselung mit öffentlichem Schlüssel (e, N)"]
B --> C["Geheimtext (Ciphertext)"]
C --> D["Entschlüsselung mit privatem Schlüssel (d)"]
D --> E["Ursprünglicher Klartext"]
F["Angreifer (Attacker)"] -- "Versucht die Primfaktorzerlegung von N" --> C
F -.-> G["Ohne p und q ist d unberechenbar"]&lt;/div>
&lt;p>Um die RSA-Kryptographie zu brechen, müssen aus dem riesigen $N$ die ursprünglichen Primzahlen $p$ und $q$ gefunden werden (Primfaktorzerlegung). Es wird geschätzt, dass selbst mit Supercomputern und der Verwendung derzeit gängiger Algorithmen (wie dem Zahlkörpersieb: GNFS) die Primfaktorzerlegung von Zahlen mit hunderten von Ziffern weitaus länger dauern würde als das Alter des Universums.&lt;/p>
&lt;hr>
&lt;h1 id="7-die-auswirkungen-der-riemannschen-vermutung-auf-die-kryptographie">7. Die Auswirkungen der Riemannschen Vermutung auf die Kryptographie
&lt;/h1>&lt;p>Wie kreuzen sich also die &amp;ldquo;Riemannsche Vermutung&amp;rdquo;, der Gipfel der reinen Mathematik, und die &amp;ldquo;Kryptographie&amp;rdquo;?&lt;/p>
&lt;h3 id="71-primzahlengenerierungsalgorithmen-primzahltest-und-die-erweiterte-riemannsche-vermutung-grh">7.1. Primzahlengenerierungsalgorithmen (Primzahltest) und die Erweiterte Riemannsche Vermutung (GRH)
&lt;/h3>&lt;p>Um die RSA-Kryptographie zu betreiben, müssen zuerst die riesigen Primzahlen $p$ und $q$ generiert werden. Es ist jedoch nicht einfach, zuverlässig und schnell zu bestimmen, &amp;ldquo;ob eine bestimmte Zahl eine Primzahl ist&amp;rdquo;.&lt;/p>
&lt;p>Gegenwärtig wird in der Praxis der &lt;strong>Miller-Rabin-Primzahltest (Miller-Rabin primality test)&lt;/strong>, ein probabilistischer Algorithmus, verwendet. Dieser Algorithmus ist schnell, birgt jedoch das Risiko von &amp;ldquo;Pseudoprimzahlen&amp;rdquo;, d.h., dass eine zusammengesetzte Zahl mit extrem geringer Wahrscheinlichkeit fälschlicherweise als Primzahl identifiziert wird.&lt;/p>
&lt;p>Wenn wir jedoch annehmen, dass die &lt;strong>&amp;ldquo;Erweiterte Riemannsche Vermutung&amp;rdquo; (Generalized Riemann Hypothesis, GRH)&lt;/strong>, die die Riemannsche Vermutung auf die Dirichletschen L-Funktionen erweitert, wahr ist, ändert sich die Situation dramatisch.
Wenn GRH wahr ist, wird eine obere Schranke für die Anzahl der Tests im Miller-Rabin-Verfahren mathematisch garantiert, und der probabilistische Algorithmus wird zu einem &lt;strong>&amp;ldquo;deterministischen Polynomialzeitalgorithmus&amp;rdquo; sublimiert&lt;/strong> (dies war eine wichtige Tatsache, die bereits vor der Entdeckung des AKS-Primzahltests bekannt war).&lt;/p>
&lt;p>Das heißt, die Riemannsche Vermutung (und ihre Erweiterung) spielt die Rolle einer direkten Garantie für die Generierung der Grundlage der Kryptographie: &amp;ldquo;Können riesige Primzahlen mit absoluter Zuverlässigkeit und hoher Geschwindigkeit generiert werden?&amp;rdquo;.&lt;/p>
&lt;h3 id="72-beziehung-zu-primfaktorzerlegungsalgorithmen">7.2. Beziehung zu Primfaktorzerlegungsalgorithmen
&lt;/h3>&lt;p>Bei der Bewertung der Komplexität von Algorithmen zur Entschlüsselung (wie dem Zahlkörpersieb) ist das Wissen über die Verteilung von Primzahlen ebenfalls unerlässlich. Viele Primfaktorzerlegungsalgorithmen basieren auf der Verteilung &amp;ldquo;glatter Zahlen (Smooth numbers: Zahlen, die nur kleine Primfaktoren haben)&amp;rdquo;.&lt;/p>
&lt;p>Um genau beurteilen zu können, wie oft glatte Zahlen auftreten, ist ein tiefes Verständnis der Primzahlverteilung erforderlich, und auch hier kommen Techniken der analytischen Zahlentheorie zum Einsatz, die direkt mit der Zeta-Funktion und der Riemannschen Vermutung verbunden sind. Wenn die Riemannsche Vermutung bewiesen ist und der Fehler in der Primzahlverteilung vollständig bestimmt ist, wird es möglich sein, die Leistungsgrenzen von Primfaktorzerlegungsalgorithmen genauer zu bestimmen.&lt;/p>
&lt;hr>
&lt;h1 id="8-wenn-die-riemannsche-vermutung-bewiesen-wird-wird-die-kryptographie-gebrochen">8. Wenn die Riemannsche Vermutung bewiesen wird, wird die Kryptographie gebrochen?
&lt;/h1>&lt;p>Wie eine urbane Legende wird oft erzählt: &amp;ldquo;Wenn die Riemannsche Vermutung gelöst ist, wird die RSA-Kryptographie in einem Augenblick zusammenbrechen&amp;rdquo;, aber &lt;strong>das ist mathematisch inkorrekt&lt;/strong>.&lt;/p>
&lt;p>Der Beweis der Riemannschen Vermutung selbst wird nicht sofort einen magischen Algorithmus hervorbringen, der die Primfaktorzerlegung drastisch beschleunigt. Die Riemannsche Vermutung ist nur ein Theorem über die &amp;ldquo;makroskopische Regelmäßigkeit der Verteilung&amp;rdquo; von Primzahlen und sagt uns nicht direkt, durch welche Primzahlen eine bestimmte Zahl $N$ teilbar ist (lokale Eigenschaften).&lt;/p>
&lt;p>Die Auswirkungen sind jedoch nicht null.
Es ist extrem wahrscheinlich, dass während des Prozesses des Beweises der Riemannschen Vermutung &lt;strong>&amp;ldquo;neue mathematische Werkzeuge&amp;rdquo; oder &amp;ldquo;unbekannte Analysemethoden&amp;rdquo; entdeckt werden&lt;/strong>. Die Geschichte zeigt, dass bei Beweisen wie dem Großen Fermatschen Satz oder der Poincaré-Vermutung neue Theorien entwickelt wurden, die die gesamte Mathematik maßgeblich vorangebracht haben.&lt;/p>
&lt;p>Sollten unbekannte Methoden der algebraischen Geometrie oder der nichtkommutativen Geometrie etabliert werden, die die Eigenschaften der Nullstellen der Riemannschen Zeta-Funktion vollständig manipulieren können, lässt sich nicht leugnen, dass dies zur Entdeckung eines bahnbrechenden Algorithmus zur Primfaktorzerlegung führen könnte (z.B. ein klassischer Algorithmus, der die Komplexität auf Polynomzeit reduziert). In diesem Sinne können Kryptographen ihre Augen niemals von den Entwicklungen rund um die Riemannsche Vermutung abwenden.&lt;/p>
&lt;h3 id="quantencomputer-und-shors-algorithmus">Quantencomputer und Shors Algorithmus
&lt;/h3>&lt;p>Eine direktere und realistischere Bedrohung für die Kryptographie ist nicht der Beweis der Riemannschen Vermutung, sondern &lt;strong>Quantencomputer&lt;/strong>. Der 1994 von Peter Shor veröffentlichte &amp;ldquo;Shor-Algorithmus&amp;rdquo; bewies, dass ein Quantencomputer mit ausreichender Leistung die Primfaktorzerlegung in Polynomzeit lösen kann. Dies würde die RSA-Kryptographie und die Elliptische-Kurven-Kryptographie grundlegend brechen.&lt;/p>
&lt;p>Derzeit wird weltweit der Übergang zur &amp;ldquo;Post-Quanten-Kryptographie (Post-Quantum Cryptography, PQC)&amp;rdquo; (wie gitterbasierte Kryptographie) vorangetrieben, die selbst von Quantencomputern nicht geknackt werden kann. Die von Primzahlen abhängige Kryptographie könnte in gewissem Sinne ihr goldenes Zeitalter beenden, aber der mathematische Wert der Primzahlen selbst wird niemals verloren gehen.&lt;/p>
&lt;hr>
&lt;h1 id="9-fazit-die-kreuzung-von-mathematischer-abstraktion-und-der-realen-gesellschaft">9. Fazit: Die Kreuzung von mathematischer Abstraktion und der realen Gesellschaft
&lt;/h1>&lt;div class="mermaid">graph TD
A["Erforschung der reinen Mathematik"] --> B["Aufklärung der Riemannschen Vermutung"]
B --> C["Vollständiges Verständnis der Primzahlverteilung"]
C --> D["Sprunghafte Entwicklung der Zahlentheorie und algebraischen Geometrie"]
D -.-> E["Möglichkeit neuer Primfaktorzerlegungsalgorithmen"]
E -.-> F["Aktualisierung der Sicherheitsbewertung von Kryptographie"]
A --> G["Angewandte Mathematik / Informatik"]
G --> H["Effizienzsteigerung bei Primzahltests und Schlüsselgenerierung"]
H --> F&lt;/div>
&lt;p>Die unersättliche Suche nach Primzahlen, die in der griechischen Antike begann, wurde von dem Genie Riemann in eine wunderschöne Sinfonie (die Nullstellen der Zeta-Funktion) auf der komplexen Ebene sublimiert. Erstaunlicherweise wird dieser reine Kristall der Mathematik Jahrhunderte später als der stärkste Schild zum Schutz der Sicherheit der Internetgesellschaft angewendet.&lt;/p>
&lt;p>Die Riemannsche Vermutung ist eine Existenz, die gleichzeitig die &amp;ldquo;abstrakte Schönheit&amp;rdquo; der Mathematik und ihre &amp;ldquo;erstaunliche Anwendbarkeit in der physischen Welt und der realen Gesellschaft&amp;rdquo; symbolisiert.&lt;/p>
&lt;p>Wenn dieser riesige mathematische Berg, dessen Gipfel noch niemand erreicht hat, eines Tages bezwungen wird, werden wir die Wahrheit des Universums der Primzahlen vollständig verstehen und eine neue Perspektive auf die Grundlagen der Informationsgesellschaft gewinnen. Das Studium der Kryptographie ist auch eine Reise, die die Geschichte der menschlichen Weisheit nachzeichnet.&lt;/p></description></item><item><title>Die Geschichte der Kryptographie: Von der Caesar-Chiffre bis zur Post-Quanten-Kryptographie (PQC)</title><link>http://kenji.blog/de/p/history-of-cryptography-caesar-to-pqc/</link><pubDate>Fri, 11 Sep 2026 15:00:00 +0900</pubDate><guid>http://kenji.blog/de/p/history-of-cryptography-caesar-to-pqc/</guid><description>&lt;img src="http://kenji.blog/p/history-of-cryptography-caesar-to-pqc/img/eyecatch.jpg" alt="Featured image of post Die Geschichte der Kryptographie: Von der Caesar-Chiffre bis zur Post-Quanten-Kryptographie (PQC)" />&lt;h1 id="1-einführung-was-ist-kryptographie">1. Einführung: Was ist Kryptographie?
&lt;/h1>&lt;p>Die Kryptographie (Kryptographie) ist die Technologie zur Wahrung der Geheimhaltung von Informationen und hat sich zusammen mit der Geschichte der Menschheit entwickelt. Von der Übermittlung geheimer Befehle in antiken Kriegen bis zum Schutz von Kreditkarteninformationen im modernen Internet ist der Zweck der Kryptographie konsistent geblieben. Er besteht darin, sicherzustellen, &amp;ldquo;dass nur der beabsichtigte Empfänger die Informationen verstehen kann und sie für Dritte nicht entschlüsselbar sind&amp;rdquo;.&lt;/p>
&lt;p>In der modernen Informationssicherheit spielt die Kryptographie nicht nur eine wichtige Rolle bei der &amp;ldquo;Geheimhaltung (Vertraulichkeit: Confidentiality)&amp;rdquo; von Informationen, sondern auch bei der &amp;ldquo;Integrität (Integrity)&amp;rdquo;, &amp;ldquo;Authentifizierung (Authentication)&amp;rdquo; und der &amp;ldquo;Nichtabstreitbarkeit (Non-repudiation)&amp;rdquo; von Daten.&lt;/p>
&lt;p>In diesem Artikel werden wir die Geschichte der Entwicklung der Kryptographie aus einer technischen und mathematischen Perspektive detailliert entwirren, beginnend mit einfachen Substitutionschiffren der Antike über mechanische Chiffren, moderne symmetrische und asymmetrische Kryptographie bis hin zur Ära der &amp;ldquo;Post-Quanten-Kryptographie (PQC)&amp;rdquo;, die mit der praktischen Anwendung von Quantencomputern anbrechen wird.&lt;/p>
&lt;hr>
&lt;h1 id="2-die-ära-der-klassischen-kryptographie-buchstaben-ersetzen-und-umstellen">2. Die Ära der klassischen Kryptographie: Buchstaben ersetzen und umstellen
&lt;/h1>&lt;p>Die Ursprünge der Kryptographie reichen bis vor die christliche Zeitrechnung zurück. Frühe Chiffren bestanden hauptsächlich aus zwei Ansätzen: &amp;ldquo;Transposition (Umstellung)&amp;rdquo; und &amp;ldquo;Substitution (Ersetzung)&amp;rdquo;.&lt;/p>
&lt;h2 id="die-skytale-chiffre-transpositionschiffre">Die Skytale-Chiffre (Transpositionschiffre)
&lt;/h2>&lt;p>Die im antiken griechischen Sparta im 5. Jahrhundert v. Chr. verwendete &amp;ldquo;Skytale (Scytale)&amp;rdquo; ist eines der ältesten kryptographischen Instrumente. Ein langer, schmaler Streifen Pergament wird um einen Holzstab einer bestimmten Dicke gewickelt und eine Nachricht wird horizontal darauf geschrieben. Wenn das Pergament abgewickelt wird, sind die Buchstaben in einer bedeutungslosen Reihenfolge angeordnet, aber ein Empfänger mit einem Stab derselben Dicke kann das Pergament erneut darumwickeln, um die ursprüngliche Nachricht zu lesen.&lt;/p>
&lt;h2 id="die-caesar-chiffre-monoalphabetische-substitutionschiffre">Die Caesar-Chiffre (Monoalphabetische Substitutionschiffre)
&lt;/h2>&lt;p>Es wird gesagt, dass Julius Caesar (Caesar), ein Held des antiken Roms im 1. Jahrhundert v. Chr., die &amp;ldquo;Caesar-Chiffre&amp;rdquo; verwendete. Dies ist eine monoalphabetische Substitutionschiffre (Monoalphabetic substitution), bei der das Alphabet um eine bestimmte Anzahl (normalerweise 3 Buchstaben) verschoben wird.&lt;/p>
&lt;p>Mathematisch gesehen, wenn wir Buchstaben als Zahlen von $0$ bis $25$ behandeln und die Verschiebung als $K$ bezeichnen, wird die Umwandlung von Klartext $P$ zu Chiffretext $C$ durch folgende Kongruenzgleichung ausgedrückt:&lt;/p>
$$C \equiv P + K \pmod{26}$$
&lt;p>Die Entschlüsselung führt die umgekehrte Operation durch:&lt;/p>
$$P \equiv C - K \pmod{26}$$
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Einfaches Python-Implementierungsbeispiel für die Caesar-Chiffre&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">mode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;encrypt&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">mode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;decrypt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shift&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">shift&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isalpha&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;A&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isupper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Verschiebungsberechnung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="nb">chr&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">base&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">26&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">char&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ausführungsbeispiel&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">plaintext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;HELLO WORLD&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plaintext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;encrypt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Chiffretext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># KHOOR ZRUOG&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="häufigkeitsanalyse-und-vigenère-chiffre">Häufigkeitsanalyse und Vigenère-Chiffre
&lt;/h2>&lt;p>Monoalphabetische Substitutionschiffren wurden durch die &amp;ldquo;Häufigkeitsanalyse (Frequency Analysis)&amp;rdquo;, die vom arabischen Gelehrten Al-Kindi im 9. Jahrhundert entwickelt wurde, leicht entschlüsselbar. Dies nutzt die statistischen Eigenschaften der Sprache, wie etwa die Häufigkeit von &amp;ldquo;E&amp;rdquo; oder &amp;ldquo;T&amp;rdquo; im Englischen.&lt;/p>
&lt;p>Um dem entgegenzuwirken, wurde im 16. Jahrhundert die &amp;ldquo;Vigenère-Chiffre (Vigenère cipher)&amp;rdquo; entwickelt. Dies ist eine polyalphabetische Substitutionschiffre (Polyalphabetic substitution), die regelmäßig zwischen mehreren Verschiebungen (Schlüsseln) wechselt und etwa 300 Jahre lang als &amp;ldquo;die unknackbare Chiffre (Le Chiffre Indéchiffrable)&amp;rdquo; bekannt war.&lt;/p>
&lt;p>Mathematisch wird sie verschlüsselt, indem der $i$-te Buchstabe des Klartextes $P_i$ und der $i$-te Buchstabe des sich wiederholenden Schlüssels $K_i$ wie folgt verwendet werden:&lt;/p>
$$C_i \equiv P_i + K_i \pmod{26}$$
&lt;p>Diese Chiffre wurde auch im 19. Jahrhundert von Charles Babbage und Friedrich Kasiski geknackt, indem sie den &amp;ldquo;Kasiski-Test (Kasiski examination)&amp;rdquo; entdeckten, der die Schlüssellänge aus sich wiederholenden Mustern im Chiffretext ermittelt.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Klassifizierung der klassischen Kryptographie"
A["Klassische Kryptographie"] --> B["Transpositionschiffre"]
A --> C["Substitutionschiffre"]
B --> D["Skytale-Chiffre"]
C --> E["Monoalphabetische Substitution"]
C --> F["Polyalphabetische Substitution"]
E --> G["Caesar-Chiffre"]
F --> H["Vigenère-Chiffre"]
end&lt;/div>
&lt;hr>
&lt;h1 id="3-mechanische-chiffren-und-weltkriege-enigma-und-ihre-entschlüsselung">3. Mechanische Chiffren und Weltkriege: Enigma und ihre Entschlüsselung
&lt;/h1>&lt;p>Zu Beginn des 20. Jahrhunderts verlagerte sich die Kommunikation von Briefen auf Telegrafen und Funk, was Schnelligkeit und Komplexität bei der Verschlüsselung erforderte. Hier traten die &amp;ldquo;mechanischen Chiffren&amp;rdquo; auf, die Rotoren (Drehscheiben) kombinierten.&lt;/p>
&lt;h2 id="die-bedrohung-der-enigma-enigma">Die Bedrohung der Enigma (Enigma)
&lt;/h2>&lt;p>Die von Nazi-Deutschland im Zweiten Weltkrieg eingesetzte &amp;ldquo;Enigma&amp;rdquo; ist die berühmteste Chiffriermaschine in der Geschichte der Kryptographie. Die Enigma bestand aus mehreren Rotoren (normalerweise 3 bis 4), einem Steckerbrett zur Vertauschung von Buchstabenverdrahtungen und einem Reflektor (Umkehrwalze).&lt;/p>
&lt;p>Da sich die Rotoren jedes Mal drehten, wenn ein Buchstabe auf der Tastatur getippt wurde, erzeugte selbst das wiederholte Tippen desselben Buchstabens unterschiedliche Chiffretextzeichen (das Extrem der polyalphabetischen Chiffre). Der Schlüsselraum (die Kombination von Einstellungen) betrug etwa $1.58 \times 10^{19}$ Möglichkeiten (etwa 15,8 Trillionen), und ein Brute-Force-Angriff galt mit der damaligen Technologie als unmöglich.&lt;/p>
&lt;h2 id="alan-turing-und-die-bombe-bombe">Alan Turing und die &amp;ldquo;Bombe (Bombe)&amp;rdquo;
&lt;/h2>&lt;p>Das Team zur Entschlüsselung von Codes in Bletchley Park in Großbritannien, das auf den frühen Arbeiten des polnischen Mathematikers Marian Rejewski und anderer aufbaute, nahm die Herausforderung dieser uneinnehmbaren Enigma an.&lt;/p>
&lt;p>Insbesondere Alan Turing entwickelte eine elektromechanische Entschlüsselungsmaschine namens &amp;ldquo;Bombe&amp;rdquo;, die Vermutungen über den Klartext (Crib) nutzte, die Teilen des Chiffretextes entsprachen. Die Bombe erkannte schnell logische Widersprüche, schloss unmögliche Rotoreinstellungen eine nach der anderen aus und entschlüsselte erfolgreich die Enigma. Man sagt, dass diese bemerkenswerte Leistung den Sieg der Alliierten um mehrere Jahre beschleunigte.&lt;/p>
&lt;hr>
&lt;h1 id="4-der-beginn-der-modernen-kryptographie-symmetrische-kryptographie-des-und-aes">4. Der Beginn der modernen Kryptographie: Symmetrische Kryptographie (DES und AES)
&lt;/h1>&lt;p>Nach dem Krieg, mit dem Aufkommen von Computern, erfuhr die Kryptographie einen dramatischen Paradigmenwechsel von der Manipulation von &amp;ldquo;Buchstaben&amp;rdquo; zur Manipulation von &amp;ldquo;Bits (0 und 1)&amp;rdquo;.&lt;/p>
&lt;h2 id="claude-shannon-und-die-informationstheorie">Claude Shannon und die Informationstheorie
&lt;/h2>&lt;p>Im Jahr 1949 veröffentlichte Claude Shannon seine Arbeit &amp;ldquo;Communication Theory of Secrecy Systems&amp;rdquo; und legte damit das mathematische Fundament für die moderne Kryptographie. Er schlug &amp;ldquo;Konfusion (Confusion)&amp;rdquo; und &amp;ldquo;Diffusion (Diffusion)&amp;rdquo; als Prinzipien für ein sicheres kryptographisches Design vor.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Konfusion (Confusion)&lt;/strong>: Die Beziehung zwischen Schlüssel und Chiffretext so komplex wie möglich gestalten. (Erreicht durch Substitution/S-Boxen)&lt;/li>
&lt;li>&lt;strong>Diffusion (Diffusion)&lt;/strong>: Sicherstellen, dass die Änderung eines einzelnen Bits im Klartext viele Bits im Chiffretext beeinflusst. (Erreicht durch Transposition/Permutation)&lt;/li>
&lt;/ul>
&lt;h2 id="des-data-encryption-standard">DES (Data Encryption Standard)
&lt;/h2>&lt;p>Im Jahr 1977 etablierte das National Institute of Standards and Technology (NIST, damals NBS) der USA &amp;ldquo;DES&amp;rdquo;, das auf einem IBM-Design basierte, als Standardverschlüsselung.
DES verwendet eine Architektur, die &amp;ldquo;Feistel-Netzwerk (Feistel Network)&amp;rdquo; genannt wird, mit einer Blocklänge von 64 Bit und einer Schlüssellänge von 56 Bit. Es hatte den Implementierungsvorteil, dass die Ver- und Entschlüsselungsalgorithmen fast die gleiche Struktur besaßen.&lt;/p>
&lt;p>Jedoch wurde mit der Verbesserung der Rechenleistung von Computern klar, dass eine Schlüssellänge von 56 Bit (etwa $7.2 \times 10^{16}$ Möglichkeiten) unzureichend war. 1998 entwickelte die Electronic Frontier Foundation (EFF) eine spezielle Maschine namens &amp;ldquo;Deep Crack&amp;rdquo; und demonstrierte, dass DES innerhalb weniger Tage geknackt werden konnte.&lt;/p>
&lt;h2 id="aes-advanced-encryption-standard">AES (Advanced Encryption Standard)
&lt;/h2>&lt;p>Als Ersatz für DES wurde im Jahr 2001 &amp;ldquo;AES&amp;rdquo; als neuer Standard etabliert. Der durch einen offenen Wettbewerb ausgewählte &amp;ldquo;Rijndael&amp;rdquo;-Algorithmus, der von belgischen Kryptographen entwickelt wurde, wurde übernommen.&lt;/p>
&lt;p>AES verwendet nicht das Feistel-Netzwerk, sondern ein &amp;ldquo;SPN-Netzwerk (Substitution-Permutation Network)&amp;rdquo; und nutzt mathematische Operationen über dem Galois-Körper (endlichen Körper) $GF(2^8)$. Die Schlüssellängen können zwischen 128, 192 oder 256 Bits gewählt werden, und es wird heute weltweit noch immer als symmetrische Standardverschlüsselung eingesetzt.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "1 Runde AES-Verarbeitung (SPN-Struktur)"
A["Eingabestatus (128-bit)"] --> B("SubBytes (Byte-Substitution / S-Box)")
B --> C("ShiftRows (Zeilenverschiebung)")
C --> D("MixColumns (Spaltenmischung / Multiplikation in GF(2^8))")
D --> E("AddRoundKey (XOR mit dem Rundenschlüssel)")
E --> F["Zur nächsten Runde"]
end&lt;/div>
&lt;hr>
&lt;h1 id="5-die-revolution-der-public-key-kryptographie-von-diffie-hellman-zu-rsa">5. Die Revolution der Public-Key-Kryptographie: Von Diffie-Hellman zu RSA
&lt;/h1>&lt;p>Die symmetrische Kryptographie hatte eine entscheidende Schwachstelle. Das war das &amp;ldquo;Schlüsselverteilungsproblem (Key Distribution Problem)&amp;rdquo;. Es war das Problem, wie ein &amp;ldquo;gemeinsamer Schlüssel&amp;rdquo; sicher mit einer weit entfernten Partei geteilt werden konnte, bevor die verschlüsselte Kommunikation begann. Dieses Problem wurde durch die &amp;ldquo;Public-Key-Kryptographie&amp;rdquo; gelöst, die in den 1970er Jahren geboren wurde.&lt;/p>
&lt;h2 id="diffie-hellman-schlüsselaustausch">Diffie-Hellman-Schlüsselaustausch
&lt;/h2>&lt;p>1976 veröffentlichten Whitfield Diffie und Martin Hellman ein bahnbrechendes Papier mit dem Titel &amp;ldquo;New Directions in Cryptography&amp;rdquo;. Sie schlugen eine Methode vor, um Schlüssel auch über einen abgehörten Kommunikationsweg sicher zu teilen, indem sie die mathematische Schwierigkeit des &amp;ldquo;diskreten Logarithmusproblems (Discrete Logarithm Problem)&amp;rdquo; ausnutzten.&lt;/p>
&lt;ol>
&lt;li>Eine große Primzahl $p$ und ein Erzeuger $g$ werden veröffentlicht.&lt;/li>
&lt;li>Alice wählt einen geheimen Wert $a$ und sendet $A = g^a \pmod{p}$ an Bob.&lt;/li>
&lt;li>Bob wählt einen geheimen Wert $b$ und sendet $B = g^b \pmod{p}$ an Alice.&lt;/li>
&lt;li>Alice berechnet $K = B^a \pmod{p}$ und Bob berechnet $K = A^b \pmod{p}$.&lt;/li>
&lt;li>Durch die Potenzgesetze wird $K = (g^b)^a = (g^a)^b = g^{ab} \pmod{p}$, und sie können wunderbar denselben Schlüssel $K$ teilen.&lt;/li>
&lt;/ol>
&lt;h2 id="rsa-kryptographie">RSA-Kryptographie
&lt;/h2>&lt;p>Im folgenden Jahr, 1977, wurde die &amp;ldquo;RSA-Kryptographie&amp;rdquo; von Ron Rivest, Adi Shamir und Leonard Adleman entwickelt. Sie basiert auf der Eigenschaft, dass &amp;ldquo;die Primfaktorzerlegung einer riesigen zusammengesetzten Zahl schwierig ist&amp;rdquo;.&lt;/p>
&lt;p>&lt;strong>Mathematischer Mechanismus von RSA:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Wähle zwei riesige Primzahlen $p$ und $q$ und berechne $n = p \times q$.&lt;/li>
&lt;li>Berechne Eulers Totient-Funktion $\phi(n) = (p-1)(q-1)$.&lt;/li>
&lt;li>Wähle eine ganze Zahl $e$ (öffentlicher Schlüssel), die teilerfremd zu $\phi(n)$ ist.&lt;/li>
&lt;li>Berechne eine ganze Zahl $d$ (privater Schlüssel), so dass $e \times d \equiv 1 \pmod{\phi(n)}$ gilt.&lt;/li>
&lt;/ol>
&lt;p>Verschlüsselung: Für den Klartext $M$, $C \equiv M^e \pmod{n}$
Entschlüsselung: Für den Chiffretext $C$, $M \equiv C^d \pmod{n}$&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Python-Code zur Veranschaulichung des RSA-Konzepts (nicht für den praktischen Einsatz)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Berechnung des modularen Inversen durch den erweiterten euklidischen Algorithmus&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">g&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">rsa_example&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Beispiel mit kleinen Primzahlen&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">61&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">53&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">17&lt;/span> &lt;span class="c1"># Wert teilerfremd zu phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">d&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">d&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Öffentlicher Schlüssel: (e=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Privater Schlüssel: (d=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Verschlüsselung und Entschlüsselung der Nachricht&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">65&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Klartext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; Chiffretext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; Entschlüsselt: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">rsa_example&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="6-der-aufstieg-der-elliptischen-kurvenkryptographie-ecc">6. Der Aufstieg der elliptischen Kurvenkryptographie (ECC)
&lt;/h1>&lt;p>Die RSA-Kryptographie ist mächtig, aber mit der Verbesserung der Computerleistung wurde es notwendig, die Schlüssellängen zu verlängern, um die Sicherheit aufrechtzuerhalten (derzeit 2048 Bit oder 3072 Bit), was zu dem Problem erhöhter Rechenkosten führte.&lt;/p>
&lt;p>Daher wurde 1985 die &amp;ldquo;Elliptische Kurvenkryptographie (Elliptic Curve Cryptography: ECC)&amp;rdquo; vorgeschlagen. Sie nutzt die Addition von Punkten auf einer elliptischen Kurve über einem endlichen Körper (im Allgemeinen in der Form $y^2 = x^3 + ax + b$).&lt;/p>
&lt;p>Es ist bekannt, dass das Problem des diskreten Logarithmus auf elliptischen Kurven (ECDLP) noch schwerer zu lösen ist als das Primfaktorzerlegungsproblem, und &lt;strong>ECC kann dieselbe Sicherheit wie RSA mit 3072 Bit mit einer Schlüssellänge von nur 256 Bit erreichen&lt;/strong>. Dies ermöglichte eine schnelle und sichere kryptographische Kommunikation (wie ECDSA und ECDH) auch in Umgebungen mit begrenzten Rechenressourcen, wie Smartphones und IoT-Geräten.&lt;/p>
&lt;hr>
&lt;h1 id="7-die-bedrohung-durch-quantencomputer-und-post-quanten-kryptographie-pqc">7. Die Bedrohung durch Quantencomputer und Post-Quanten-Kryptographie (PQC)
&lt;/h1>&lt;p>Die Kryptographie schien unerschütterlich, bis Peter Shor 1994 &amp;ldquo;Shors Algorithmus&amp;rdquo; veröffentlichte, was einen gewaltigen Schock auslöste.&lt;/p>
&lt;p>Quantencomputer führen Berechnungen durch, indem sie die quantenmechanischen Eigenschaften der &amp;ldquo;Superposition&amp;rdquo; und der &amp;ldquo;Quantenverschränkung&amp;rdquo; ausnutzen. Wenn Shors Algorithmus auf einem ausreichend leistungsstarken Quantencomputer ausgeführt wird, wurde mathematisch bewiesen, dass das Primfaktorzerlegungsproblem und das diskrete Logarithmusproblem in &amp;ldquo;polynomieller Zeit&amp;rdquo; gelöst werden können. Das bedeutet, dass an dem Tag, an dem ein praktischer Quantencomputer fertiggestellt wird (Q-Day), alle derzeit verwendeten Public-Key-Kryptographien wie RSA und ECC sofort zusammenbrechen werden.&lt;/p>
&lt;h2 id="die-entstehung-von-pqc-post-quantum-cryptography">Die Entstehung von PQC (Post-Quantum Cryptography)
&lt;/h2>&lt;p>Um sich auf diese beispiellose Bedrohung vorzubereiten, schreitet die Forschung an &amp;ldquo;Post-Quanten-Kryptographie (PQC)&amp;rdquo; in schnellem Tempo voran, basierend auf neuen mathematischen Problemen, die selbst für Quantencomputer schwer zu lösen sind. Das NIST (National Institute of Standards and Technology der USA) führt seit vielen Jahren einen PQC-Standardisierungsprozess durch, bei dem hauptsächlich die folgenden mathematischen Ansätze als vielversprechend angesehen werden.&lt;/p>
&lt;h3 id="1-gitterbasierte-kryptographie-lattice-based-cryptography">1. Gitterbasierte Kryptographie (Lattice-based Cryptography)
&lt;/h3>&lt;p>Dies ist derzeit der vielversprechendste Ansatz und wurde in den Standardisierungsalgorithmen von NIST (ML-KEM / Kyber, ML-DSA / Dilithium) übernommen. Es basiert auf der Schwierigkeit, bestimmte Punkte auf einem &amp;ldquo;Gitter (Lattice)&amp;rdquo; in mehrdimensionalen Räumen zu finden (Shortest Vector Problem: SVP usw.) oder auf dem LWE-Problem (Learning With Errors).&lt;/p>
&lt;p>Das Konzept des LWE-Problems nutzt die Eigenschaft, dass das Finden einer Lösung extrem schwierig wird, wenn man absichtlich &amp;ldquo;kleines Rauschen (Fehler)&amp;rdquo; zu einem System linearer Gleichungen hinzufügt.
Gleichungssystem: $\mathbf{A}\mathbf{s} + \mathbf{e} \equiv \mathbf{b} \pmod{q}$
($\mathbf{A}$ und $\mathbf{b}$ sind öffentlich, $\mathbf{s}$ ist der private Schlüssel und $\mathbf{e}$ ist minimales Rauschen)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Konzeptueller Pseudocode des LWE-Problems (zu Lernzwecken)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span> &lt;span class="c1"># Dimension&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3329&lt;/span> &lt;span class="c1"># Modul&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">512&lt;/span> &lt;span class="c1"># Anzahl der Gleichungen&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"># Privater Schlüssel s und kleiner Fehler e&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Öffentliche Matrix A und öffentlicher Vektor b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">A&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Selbst mit einem Quantencomputer wird es als extrem schwierig angesehen, s aus A und b wiederherzustellen&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="2-hash-basierte-kryptographie-hash-based-cryptography">2. Hash-basierte Kryptographie (Hash-based Cryptography)
&lt;/h3>&lt;p>Ein digitales Signaturschema, das seine Sicherheit ausschließlich auf die Kollisionsresistenz von Hash-Funktionen stützt. Da es keine mathematische Struktur besitzt, ist es widerstandsfähig gegen Quantenangriffe, neigt jedoch zu großen Signaturgrößen (wie SPHINCS+).&lt;/p>
&lt;h3 id="3-code-basierte-kryptographie-code-based-cryptography">3. Code-basierte Kryptographie (Code-based Cryptography)
&lt;/h3>&lt;p>Ein kryptographisches Verfahren, das auf der Theorie fehlerkorrigierender Codes basiert. Das 1978 vorgeschlagene McEliece-Kryptosystem ist ein berühmtes Beispiel; es hat eine lange Geschichte und einen etablierten Ruf für Sicherheit, leidet jedoch unter dem Problem sehr großer öffentlicher Schlüssel (die manchmal mehrere Megabyte erreichen).&lt;/p>
&lt;div class="mermaid">timeline
title "Die Geschichte der Kryptographie und der Computerentwicklung"
"Antike bis Mittelalter" : "Caesar-Chiffre" : "Vigenère-Chiffre" : "Geburt der Häufigkeitsanalyse"
"1930er bis 1940er" : "Einsatz und Entschlüsselung der Enigma" : "Entwicklung der Turing-Maschine / Bombe"
"1970er" : "DES-Standardisierung (1977)" : "Diffie-Hellman-Schlüsselaustausch (1976)" : "Geburt der RSA-Kryptographie (1977)"
"1980er bis 1990er" : "Vorschlag der Elliptischen Kurvenkryptographie (ECC)" : "Veröffentlichung von Shors Algorithmus (1994)"
"2000er" : "AES-Standardisierung (2001)"
"2010er bis Gegenwart" : "Beschleunigung der Quantencomputerforschung" : "Start des PQC-Standardisierungsprojekts durch NIST"
"Nahe Zukunft (Q-Day)" : "Realisierung eines großangelegten Quantencomputers?" : "Vollständiger Übergang zu PQC (ML-KEM/ML-DSA)"&lt;/div>
&lt;hr>
&lt;h1 id="8-fazit-der-endlose-kampf-zwischen-schild-und-speer">8. Fazit: Der endlose Kampf zwischen Schild und Speer
&lt;/h1>&lt;p>Die Geschichte der Kryptographie ist eine Geschichte des endlosen Kampfes zwischen der Erfindung neuer Verschlüsselungsmethoden (Schilde) und neuen Entschlüsselungstechniken (Speere), um sie zu durchbrechen.&lt;/p>
&lt;p>Die Caesar-Chiffre wurde durch die Häufigkeitsanalyse besiegt, und die unbesiegbare Enigma wurde durch Turings geniales Gehirn und die Kraft der Maschinen besiegt. Und nun sind starke Chiffren wie RSA und ECC, die das Fundament der modernen Internetgesellschaft stützen, durch den neuen &amp;ldquo;Speer&amp;rdquo; der Quantencomputer bedroht.&lt;/p>
&lt;p>Doch die Menschheit blickt bereits auf diese zukünftige Zeit und bereitet einen neuen &amp;ldquo;Schild&amp;rdquo; namens Post-Quanten-Kryptographie (PQC) vor. Gegenwärtig ist die Vorbereitung des Übergangs von bestehender Public-Key-Kryptographie zu PQC (Sicherstellung von Krypto-Agilität) eine dringende Aufgabe für IT-Infrastrukturen weltweit.&lt;/p>
&lt;p>Die Kryptographie ist nicht nur ein obskures mathematisches Rätsel, sondern die stärkste Verteidigungsmauer, um unsere Privatsphäre, unser Eigentum und die Gesellschaftsinfrastruktur selbst zu schützen.&lt;/p></description></item><item><title>【Mathematik-Erklärung】Wie RSA-Verschlüsselung funktioniert, verständlich für Schüler erklärt</title><link>http://kenji.blog/de/p/rsa-encryption-math-explained-for-beginners/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/de/p/rsa-encryption-math-explained-for-beginners/</guid><description>&lt;img src="http://kenji.blog/p/rsa-encryption-math-explained-for-beginners/img/eyecatch.jpg" alt="Featured image of post 【Mathematik-Erklärung】Wie RSA-Verschlüsselung funktioniert, verständlich für Schüler erklärt" />&lt;p>Eine der Technologien, die die Sicherheit der Internetgesellschaft grundlegend unterstützt, ist die „RSA-Verschlüsselung“. Viele der Kommunikationen, die wir jeden Tag beiläufig nutzen, wie Kreditkartenzahlungen beim Online-Shopping, der Austausch mit Freunden auf sozialen Netzwerken und das Senden und Empfangen vertraulicher Unternehmensinformationen, werden durch diese RSA-Verschlüsselung und ihre Nachfolgetechnologien geschützt.&lt;/p>
&lt;p>Wenn man jedoch das Wort „Verschlüsselung“ hört, stellt man sich vielleicht komplexe Chiffriermaschinen wie in Spionagefilmen vor oder extrem fortgeschrittene Mathematik, die nur einige wenige Genies verstehen können. Es stimmt zwar, dass die moderne Kryptographie auf fortgeschrittener Mathematik basiert, aber &lt;strong>die grundlegende Funktionsweise der RSA-Verschlüsselung kann mit dem Wissen aus der Schulmathematik (Eigenschaften von ganzen Zahlen, Primzahlen, Kongruenzen usw.) gut verstanden werden&lt;/strong>.&lt;/p>
&lt;p>In diesem Artikel erklären wir ausgehend vom Wissen der Schulmathematik Schritt für Schritt, nach welchen mathematischen Prinzipien die RSA-Verschlüsselung funktioniert und warum sie so schwer zu knacken ist. Wir werden es anhand konkreter Beispiele sorgfältig erklären, so dass auch diejenigen es verstehen können, die in Mathematik vielleicht nicht so stark sind.&lt;/p>
&lt;hr>
&lt;h2 id="1-symmetrische-verschlüsselung-und-asymmetrische-verschlüsselung-public-key-verschlüsselung">1. Symmetrische Verschlüsselung und asymmetrische Verschlüsselung (Public-Key-Verschlüsselung)
&lt;/h2>&lt;p>Bevor wir uns mit den mathematischen Mechanismen der RSA-Verschlüsselung befassen, lassen Sie uns zunächst die Grundkonzepte der Kryptographie klären. Verschlüsselungsverfahren lassen sich grob in zwei Arten unterteilen: die „symmetrische Verschlüsselung“ und die „asymmetrische Verschlüsselung“ (Public-Key-Kryptographie).&lt;/p>
&lt;h3 id="11-die-grenzen-der-symmetrischen-verschlüsselung">1.1 Die Grenzen der symmetrischen Verschlüsselung
&lt;/h3>&lt;p>Viele der seit langem verwendeten Verschlüsselungen sind sogenannte „symmetrische Verschlüsselungsverfahren“. Bei dieser Methode wird &lt;strong>für die „Verschlüsselung“ (die Umwandlung einer Nachricht in einen geheimen Geheimtext) und die „Entschlüsselung“ (die Wiederherstellung der ursprünglichen Nachricht aus dem Geheimtext) derselbe Schlüssel verwendet&lt;/strong>.&lt;/p>
&lt;p>Nehmen wir zum Beispiel an, Alice möchte Bob einen geheimen Brief schicken. Alice legt den Brief in eine Kiste und verschließt diese mit einem Vorhängeschloss (dem symmetrischen Schlüssel). Damit Bob diese Kiste öffnen kann, muss er denselben Schlüssel besitzen, den auch Alice benutzt hat.&lt;/p>
&lt;p>Dieses System hat ein großes Problem: das „Schlüsselaustauschproblem“. Wenn Alice und Bob, die weit voneinander entfernt sind, zum ersten Mal kommunizieren, wie können sie dann einen Schlüssel teilen, ohne abgehört zu werden? Wenn der Schlüssel auf dem Postweg von einem Dritten gestohlen wird, ist die gesamte nachfolgende verschlüsselte Kommunikation für diesen einsehbar.&lt;/p>
&lt;h3 id="12-die-bahnbrechende-erfindung-der-asymmetrischen-verschlüsselung">1.2 Die bahnbrechende Erfindung der „asymmetrischen Verschlüsselung“
&lt;/h3>&lt;p>Um dieses Schlüsselaustauschproblem zu lösen, wurde die „asymmetrische Verschlüsselung“ erfunden. Die RSA-Verschlüsselung ist eine Form davon.&lt;/p>
&lt;p>Bei der asymmetrischen Verschlüsselung werden &lt;strong>zwei unterschiedliche Schlüssel verwendet: ein „Schlüssel zum Verschlüsseln (öffentlicher Schlüssel)“ und ein „Schlüssel zum Entschlüsseln (privater Schlüssel)“&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Der Empfänger Bob erstellt ein Paar aus „öffentlichem Schlüssel“ und „privatem Schlüssel“.&lt;/li>
&lt;li>Bob veröffentlicht den „öffentlichen Schlüssel“ für die ganze Welt (es spielt keine Rolle, wer ihn bekommt).&lt;/li>
&lt;li>Die Senderin Alice verschlüsselt ihre Nachricht mit Bobs „öffentlichem Schlüssel“ und sendet sie ab.&lt;/li>
&lt;li>Die verschlüsselte Nachricht kann nur mit dem „privaten Schlüssel“, den nur Bob besitzt, entschlüsselt werden.&lt;/li>
&lt;/ol>
&lt;p>Um dies mit einem Vorhängeschloss zu vergleichen: Bob stellt viele „offene Vorhängeschlösser (öffentliche Schlüssel)“ her und verteilt sie in der ganzen Welt. Alice legt eine Nachricht für Bob in eine Kiste und verschließt sie mit einem gefundenen Vorhängeschloss von Bob. Sobald das Vorhängeschloss geschlossen ist, kann es nur noch mit dem „Generalschlüssel (privater Schlüssel)“ geöffnet werden, den Bob besitzt. Selbst wenn jemand unterwegs die Kiste stiehlt, kann er sie ohne den Generalschlüssel nicht öffnen.&lt;/p>
&lt;div class="mermaid">graph TD
A["Alice (Senderin)"] --> B["Klartext (Nachricht)"]
B --> C["Verschlüsselungsprozess"]
D["Bobs öffentlicher Schlüssel (für jeden zugänglich)"] --> C
C --> E["Versand über das Internet: Geheimtext"]
E --> F["Entschlüsselungsprozess"]
G["Bobs privater Schlüssel (nur Bob hat ihn)"] --> F
F --> H["Wiederhergestellter Klartext (Nachricht)"]
H --> I["Bob (Empfänger)"]&lt;/div>
&lt;p>Um dieses revolutionäre System zu realisieren, ist eine Art &lt;strong>„Einwegfunktion (ein mathematisches Einbahnstraßen-Rätsel)“&lt;/strong> erforderlich, die es erlaubt, „mit dem öffentlichen Schlüssel leicht zu verschlüsseln, aber ohne den privaten Schlüssel absolut nicht zu entschlüsseln“. Als Bestandteil dieses Rätsels richtete man die Aufmerksamkeit auf etwas, das wir gut kennen: „Primzahlen“.&lt;/p>
&lt;hr>
&lt;h2 id="2-mathematische-grundlagen-der-rsa-verschlüsselung-teil-1-primzahlen-und-primfaktorzerlegung">2. Mathematische Grundlagen der RSA-Verschlüsselung Teil 1: Primzahlen und Primfaktorzerlegung
&lt;/h2>&lt;p>Die Sicherheit der RSA-Verschlüsselung basiert auf der mathematischen Tatsache, dass &lt;strong>„die Primfaktorzerlegung riesiger Zahlen extrem schwierig ist“&lt;/strong>.&lt;/p>
&lt;h3 id="21-was-sind-primzahlen">2.1 Was sind Primzahlen?
&lt;/h3>&lt;p>Eine Primzahl ist „eine natürliche Zahl größer als 1, die nur durch 1 und durch sich selbst teilbar ist“.
Beispiel: $2, 3, 5, 7, 11, 13, 17, 19, 23...$&lt;/p>
&lt;p>Primzahlen sind wie die „Atome“ aller ganzen Zahlen. Jede natürliche Zahl kann in eine Multiplikation von Primzahlen zerlegt werden. Dies nennt man &lt;strong>Primfaktorzerlegung&lt;/strong>. Dass sich eine Zahl, abgesehen von der Reihenfolge der Faktoren, auf genau eine Weise in Primfaktoren zerlegen lässt (wie z. B. $60 = 2^2 \times 3 \times 5$), ist als der „Fundamentalsatz der Arithmetik“ bekannt.&lt;/p>
&lt;h3 id="22-die-schwierigkeit-der-primfaktorzerlegung-einwegfunktion">2.2 Die Schwierigkeit der Primfaktorzerlegung (Einwegfunktion)
&lt;/h3>&lt;p>Wichtig ist hier die Asymmetrie: &lt;strong>„Multiplizieren ist einfach, aber die Primfaktorzerlegung ist schwierig.“&lt;/strong>&lt;/p>
&lt;p>Versuchen Sie beispielsweise, die Multiplikation der folgenden zwei Primzahlen im Kopf zu berechnen:
$11 \times 13 = ?$
Das ist einfach. Die Antwort ist $143$.&lt;/p>
&lt;p>Aber wie steht es mit der nächsten Zahl?
Bitte zerlegen Sie $323$ in ihre Primfaktoren.
Wie sieht es aus? Das dürfte ein wenig Zeit in Anspruch nehmen. (Die Antwort ist $17 \times 19$).&lt;/p>
&lt;p>Wenn die Zahlen klein sind, kann ein Mensch sie irgendwie noch berechnen, aber wenn die Zahlen größer werden, wird die Berechnung selbst für Computer explosiv schwierig. Die derzeit vorherrschende RSA-Verschlüsselung verwendet eine Zahl $N = p \times q$, die das Produkt aus zwei unfassbar riesigen Primzahlen $p$ und $q$ von 2048 Bit (etwa 600 Dezimalstellen) ist.&lt;/p>
&lt;p>Wenn zwei riesige Primzahlen $p$ und $q$ gegeben sind, ist die Berechnung von $N$ für einen Computer eine Sache von Millisekunden. Wenn man jedoch nur $N$ hat und die ursprünglichen $p$ und $q$ finden möchte, würde dies so lange dauern, dass selbst der derzeit schnellste Supercomputer das Problem in Billionen von Jahren nicht lösen könnte.&lt;/p>
&lt;p>Diese &lt;strong>„Asymmetrie der Berechnung (in eine Richtung einfach, in die andere extrem schwer)“&lt;/strong> bildet die Grundlage für die Beziehung zwischen dem öffentlichen und dem privaten Schlüssel.&lt;/p>
&lt;hr>
&lt;h2 id="3-mathematische-grundlagen-der-rsa-verschlüsselung-teil-2-kongruenzen-modulo-arithmetik">3. Mathematische Grundlagen der RSA-Verschlüsselung Teil 2: Kongruenzen (Modulo-Arithmetik)
&lt;/h2>&lt;p>Die Berechnungen bei der RSA-Verschlüsselung erfolgen nicht wie bei der gewöhnlichen Addition oder Multiplikation, bei der die Zahlen unendlich groß werden, sondern in einer Welt der „Reste“, die entstehen, wenn man durch eine bestimmte Zahl teilt. Dies wird als &lt;strong>Kongruenz (Modulo-Arithmetik)&lt;/strong> bezeichnet.&lt;/p>
&lt;h3 id="31-die-mathematik-der-uhr">3.1 Die Mathematik der Uhr
&lt;/h3>&lt;p>Die Modulo-Arithmetik wird oft mit der „Mathematik der Uhr“ verglichen. Angenommen, es ist jetzt 10 Uhr, wie spät ist es in 5 Stunden? $10 + 5 = 15$ Uhr, aber auf einer normalen 12-Stunden-Uhr würden wir „3 Uhr“ sagen. Das liegt daran, dass der Rest von 15 geteilt durch 12 gleich 3 ist.&lt;/p>
&lt;p>In der Welt der Mathematik wird dies wie folgt geschrieben:
&lt;/p>
$$ 15 \equiv 3 \pmod{12} $$
&lt;p>
Man liest dies als: „15 und 3 sind kongruent modulo 12 (sie haben denselben Rest, wenn man sie durch 12 teilt).“&lt;/p>
&lt;h3 id="32-grundlegende-eigenschaften-von-kongruenzen">3.2 Grundlegende Eigenschaften von Kongruenzen
&lt;/h3>&lt;p>Kongruenzen haben sehr nützliche Eigenschaften, die denen einer Gleichung ($=$) sehr ähnlich sind. Sei das Modul (die Zahl, durch die geteilt wird) $N$.
Wenn $a \equiv b \pmod N$ und $c \equiv d \pmod N$, dann gilt Folgendes:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition:&lt;/strong> $a + c \equiv b + d \pmod N$&lt;/li>
&lt;li>&lt;strong>Subtraktion:&lt;/strong> $a - c \equiv b - d \pmod N$&lt;/li>
&lt;li>&lt;strong>Multiplikation:&lt;/strong> $a \times c \equiv b \times d \pmod N$&lt;/li>
&lt;li>&lt;strong>Potenzieren:&lt;/strong> $a^k \equiv b^k \pmod N$ (wobei $k$ eine natürliche Zahl ist)&lt;/li>
&lt;/ol>
&lt;p>Besonders wichtig ist die Eigenschaft des „Potenzierens“. Das bedeutet: &lt;strong>„Die Potenz eines Restes ist kongruent zum Rest der Potenz.“&lt;/strong>
Angenommen, wir wollen den Rest ermitteln, wenn $7^{100}$ durch $5$ geteilt wird. Es wäre mühsam, $7$ ernsthaft 100 Mal mit sich selbst zu multiplizieren und dann durch $5$ zu teilen. Wenn wir jedoch die Eigenschaften von Kongruenzen nutzen, wissen wir, dass $7 \equiv 2 \pmod 5$ ist, also gilt $7^{100} \equiv 2^{100} \pmod 5$. Dadurch lässt sich die Berechnung drastisch vereinfachen. Da in der Welt der Kryptographie mit sehr großen Potenzen gerechnet wird, ist diese Eigenschaft unverzichtbar.&lt;/p>
&lt;hr>
&lt;h2 id="4-mathematische-grundlagen-der-rsa-verschlüsselung-teil-3-eulersche-phi-funktion-und-der-satz-von-euler">4. Mathematische Grundlagen der RSA-Verschlüsselung Teil 3: Eulersche Phi-Funktion und der Satz von Euler
&lt;/h2>&lt;p>Hier beginnt nun die magische Mathematik, die den Kern der RSA-Verschlüsselung ausmacht. Hier kommt der „Satz von Euler“ ins Spiel, der eine Verallgemeinerung des „kleinen fermatschen Satzes“ ist.&lt;/p>
&lt;h3 id="41-die-eulersche-totient-funktion-phin">4.1 Die Eulersche Totient-Funktion $\phi(N)$
&lt;/h3>&lt;p>Die Eulersche Totient-Funktion (auch $\phi$-Funktion genannt) gibt für eine natürliche Zahl $N$ &lt;strong>„die Anzahl der natürlichen Zahlen von 1 bis $N$, die teilerfremd zu $N$ sind (deren größter gemeinsamer Teiler 1 ist)“&lt;/strong>, zurück.&lt;/p>
&lt;p>Schauen wir uns einige Beispiele an.&lt;/p>
&lt;ul>
&lt;li>$\phi(5)$: Unter 1, 2, 3, 4 und 5 sind 1, 2, 3 und 4 teilerfremd zu 5 (also 4 Zahlen). Daher ist $\phi(5) = 4$.&lt;/li>
&lt;li>$\phi(6)$: Unter 1, 2, 3, 4, 5 und 6 sind 1 und 5 teilerfremd zu 6 (also 2 Zahlen). Daher ist $\phi(6) = 2$.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Spezielle Eigenschaft bei Primzahlen]&lt;/strong>
Wenn $p$ eine Primzahl ist, sind alle Zahlen von 1 bis $p-1$ teilerfremd zu $p$. Daher gilt:
&lt;/p>
$$ \phi(p) = p - 1 $$
&lt;p>&lt;strong>[Spezielle Eigenschaft beim Produkt von Primzahlen]&lt;/strong>
Für zwei verschiedene Primzahlen $p$ und $q$ und $N = p \times q$ kann $\phi(N)$ einfach durch folgende Berechnung ermittelt werden:
&lt;/p>
$$ \phi(N) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$
&lt;p>
Diese Eigenschaft fungiert als „geheime Hintertür (Trapdoor)“ der RSA-Verschlüsselung. Wer $p$ und $q$ kennt (der Ersteller des Schlüssels), kann $\phi(N)$ augenblicklich berechnen, aber ein Dritter, der nur $N$ kennt, kann $\phi(N)$ nicht bestimmen, ohne $N$ vorher in seine Primfaktoren zu zerlegen.&lt;/p>
&lt;h3 id="42-der-satz-von-euler">4.2 Der Satz von Euler
&lt;/h3>&lt;p>Leonhard Euler bewies mit Hilfe dieser Funktion $\phi(N)$ den folgenden schönen Satz.&lt;/p>
&lt;p>&lt;strong>Der Satz von Euler:&lt;/strong>
Wenn eine ganze Zahl $a$ und $N$ teilerfremd sind, gilt die folgende Kongruenz:
&lt;/p>
$$ a^{\phi(N)} \equiv 1 \pmod N $$
&lt;p>Das ist die bemerkenswerte Eigenschaft, dass „wenn man eine bestimmte Zahl $a$ insgesamt $\phi(N)$ Mal mit sich selbst multipliziert und durch $N$ teilt, der Rest immer $1$ ist“. (Wenn $N$ eine Primzahl $p$ ist, ergibt sich $a^{p-1} \equiv 1 \pmod p$, was als der kleine fermatsche Satz bekannt ist).&lt;/p>
&lt;p>Lassen Sie uns diesen Satz von Euler umformen. Wir multiplizieren beide Seiten noch einmal mit $a$.
&lt;/p>
$$ a^{\phi(N) + 1} \equiv a \pmod N $$
&lt;p>Darüber hinaus ergibt $a^{k \cdot \phi(N)}$ für eine beliebige ganze Zahl $k$ ebenfalls $1^k = 1$, sodass die folgende Gleichung gilt:
&lt;/p>
$$ a^{k \cdot \phi(N) + 1} \equiv a \pmod N $$
&lt;p>Genau diese Gleichung ist das Grundprinzip, das die Magie der RSA-Verschlüsselung – &lt;strong>„nach dem Verschlüsseln und Entschlüsseln erhält man wieder das Original“&lt;/strong> – möglich macht.&lt;/p>
&lt;hr>
&lt;h2 id="5-der-algorithmus-der-rsa-verschlüsselung-schritte-zur-schlüsselerzeugung-verschlüsselung-und-entschlüsselung">5. Der Algorithmus der RSA-Verschlüsselung: Schritte zur Schlüsselerzeugung, Verschlüsselung und Entschlüsselung
&lt;/h2>&lt;p>Da wir nun über das Grundlagenwissen verfügen, schauen wir uns endlich die konkreten Schritte der RSA-Verschlüsselung an. Die RSA-Verschlüsselung ist grob in drei Phasen unterteilt: „1. Schlüsselerzeugung“, „2. Verschlüsselung“ und „3. Entschlüsselung“.&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Wähle Primzahlen p, q"] --> A2["Berechne N = p × q"]
A1 --> A3["Berechne φ(N) = (p-1)(q-1)"]
A3 --> A4["Wähle ein e, das zu φ(N) teilerfremd ist"]
A3 --> A5["Berechne d, sodass e × d ≡ 1 (mod φ(N))"]
A2 --> A6["Öffentlicher Schlüssel (N, e)"]
A4 --> A6
A5 --> A7["Privater Schlüssel d"]
B1["2. Klartext-Nachricht M"] --> B2["Berechne C ≡ M^e (mod N)"]
A6 -.-> B2
B2 --> B3["Sende Geheimtext C"]
B3 --> C1["3. Empfangener Geheimtext C"]
C1 --> C2["Berechne M ≡ C^d (mod N)"]
A7 -.-> C2
C2 --> C3["Erhalte ursprüngliche Klartext-Nachricht M"]&lt;/div>
&lt;h3 id="51-schlüsselerzeugung-key-generation">5.1 Schlüsselerzeugung (Key Generation)
&lt;/h3>&lt;p>Bob, der Empfänger, generiert für sich selbst einen „öffentlichen Schlüssel“ und einen „privaten Schlüssel“.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Wahl der Primzahlen:&lt;/strong> Es werden zwei große Primzahlen $p$ und $q$ zufällig gewählt.&lt;/li>
&lt;li>&lt;strong>Berechnung des Moduls $N$:&lt;/strong> Es wird $N = p \times q$ berechnet. Dieses $N$ wird veröffentlicht.&lt;/li>
&lt;li>&lt;strong>Berechnung von $\phi(N)$:&lt;/strong> Die Eulersche Funktion $\phi(N) = (p - 1)(q - 1)$ wird berechnet. Diese Zahl ist Bobs Geheimnis.&lt;/li>
&lt;li>&lt;strong>Wahl des öffentlichen Schlüssels $e$:&lt;/strong> Es wird eine ganze Zahl $e$ gewählt, für die $1 &lt; e &lt; \phi(N)$ gilt und die teilerfremd zu $\phi(N)$ ist.&lt;/li>
&lt;li>&lt;strong>Berechnung des privaten Schlüssels $d$:&lt;/strong> Es wird eine ganze Zahl $d$ gefunden, die folgende Bedingung erfüllt:
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
Das bedeutet: „Eine Zahl $d$, bei der $e \times d$ geteilt durch $\phi(N)$ einen Rest von $1$ ergibt.“&lt;/li>
&lt;/ol>
&lt;p>Damit sind die Schlüssel vorbereitet.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Öffentlicher Schlüssel:&lt;/strong> Das Paar $(N, e)$. Es wird für die ganze Welt veröffentlicht.&lt;/li>
&lt;li>&lt;strong>Privater Schlüssel:&lt;/strong> $d$. Er wird absolut niemandem verraten.&lt;/li>
&lt;/ul>
&lt;h3 id="52-verschlüsselung-encryption">5.2 Verschlüsselung (Encryption)
&lt;/h3>&lt;p>Angenommen, Alice möchte Bob eine geheime Nachricht $M$ senden. ($M$ ist ein in Zahlen umgewandelter Text, wobei $0 \le M &lt; N$ gilt). Alice berechnet mithilfe von Bobs öffentlichem Schlüssel $(N, e)$ Folgendes:&lt;/p>
$$ C \equiv M^e \pmod N $$
&lt;p>Sie berechnet „den Rest $C$, der entsteht, wenn man die Nachricht $M$ mit $e$ potenziert und durch $N$ teilt“. Dieses $C$ ist der Geheimtext.&lt;/p>
&lt;h3 id="53-entschlüsselung-decryption">5.3 Entschlüsselung (Decryption)
&lt;/h3>&lt;p>Bob empfängt den Geheimtext $C$. Bob rechnet mit seinem privaten Schlüssel $d$ wie folgt:&lt;/p>
$$ M \equiv C^d \pmod N $$
&lt;p>Wenn man „den Rest berechnet, der entsteht, wenn der Geheimtext $C$ mit $d$ potenziert und durch $N$ geteilt wird“, wird erstaunlicherweise die ursprüngliche Nachricht $M$ wiederhergestellt!&lt;/p>
&lt;hr>
&lt;h2 id="6-warum-erhält-man-durch-entschlüsselung-das-original-zurück-mathematischer-beweis">6. Warum erhält man durch Entschlüsselung das Original zurück? (Mathematischer Beweis)
&lt;/h2>&lt;p>Vielleicht fragen Sie sich: „Wie kann es sein, dass $C$ hoch $d$ uns einfach unser ursprüngliches $M$ zurückgibt?“ Hier kommt nun der zuvor erwähnte „Satz von Euler“ ins Spiel.&lt;/p>
&lt;p>Setzen wir die Formel für die Verschlüsselung, $C = M^e$, in die Berechnungsformel für die Entschlüsselung, $C^d \pmod N$, ein.
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Erinnern wir uns nun an Schritt 5 der Schlüsselerzeugung. Als Bob $d$ generierte, wählte er es so, dass $e \times d \equiv 1 \pmod{\phi(N)}$ gilt. Das bedeutet, dass „$ed$ ein Vielfaches von $\phi(N)$ plus $1$ ist“. Mit einer ganzen Zahl $k$ lässt sich dies wie folgt schreiben:
&lt;/p>
$$ ed = k \cdot \phi(N) + 1 $$
&lt;p>Wir setzen dies in den Exponenten ein und zerlegen ihn mithilfe der Potenzgesetze.
&lt;/p>
$$ M^{ed} = M^{k \cdot \phi(N) + 1} = M^{k \cdot \phi(N)} \times M^1 = (M^{\phi(N)})^k \times M $$
&lt;p>Wenn wir hier annehmen, dass die Nachricht $M$ und $N$ teilerfremd sind, gilt nach dem &lt;strong>Satz von Euler&lt;/strong> $M^{\phi(N)} \equiv 1 \pmod N$.
&lt;/p>
$$ (M^{\phi(N)})^k \times M \equiv 1^k \times M \equiv M \pmod N $$
&lt;p>Folglich ergibt sich auf wunderbare Weise diese Gleichung:
&lt;/p>
$$ C^d \equiv M \pmod N $$
&lt;p>Da Alice $d$ nicht kennt und auch ein Abhörer $d$ nicht kennt, ist Bob mit seinem $d$ der Einzige, der $M$ aus $C$ extrahieren kann.&lt;/p>
&lt;hr>
&lt;h2 id="7-ein-konkretes-beispiel-rsa-mit-kleinen-primzahlen-per-hand-ausprobieren">7. Ein konkretes Beispiel: RSA mit kleinen Primzahlen per Hand ausprobieren
&lt;/h2>&lt;p>Lassen Sie uns tatsächlich eine verschlüsselte Kommunikation von Alice an Bob unter Verwendung kleiner Zahlen (Primzahlen) durchführen.&lt;/p>
&lt;p>&lt;strong>[Bobs Schlüsselerzeugungsphase]&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Er wählt zwei Primzahlen: $p=11$, $q=13$.&lt;/li>
&lt;li>Er berechnet $N = 11 \times 13 = 143$.&lt;/li>
&lt;li>Er berechnet $\phi(N) = (11 - 1) \times (13 - 1) = 10 \times 12 = 120$.&lt;/li>
&lt;li>Er wählt einen öffentlichen Schlüssel $e$, der teilerfremd zu $\phi(N)=120$ ist. Hier wählen wir $e=7$.&lt;/li>
&lt;li>Er ermittelt den privaten Schlüssel $d$. Er sucht ein $d$, für das $7 \times d \equiv 1 \pmod{120}$ gilt.
In der Gleichung $7d = 120k + 1$ ergibt sich für $k=6$ die Zahl $721$, und $721 \div 7 = 103$.
Daher ist $d = 103$.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Öffentlicher Schlüssel: $(N=143, e=7)$&lt;/li>
&lt;li>Privater Schlüssel: $d=103$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Alices Verschlüsselungsphase]&lt;/strong>
Nehmen wir an, sie möchte die Nachricht $M = 9$ senden.
Formel: $C \equiv 9^7 \pmod{143}$
$9^7 = 4.782.969$. Teilt man dies durch 143, erhält man $33447$ mit dem Rest $48$.
Der Geheimtext $C$ ist also $48$.&lt;/p>
&lt;p>&lt;strong>[Bobs Entschlüsselungsphase]&lt;/strong>
Bob empfängt den Geheimtext $C = 48$ und entschlüsselt ihn mit dem privaten Schlüssel $d = 103$.
Formel: $M \equiv 48^{103} \pmod{143}$
Wenn man &lt;code>(48 ** 103) % 143&lt;/code> in einen Computer eingibt, ist das großartige Ergebnis tatsächlich „&lt;strong>9&lt;/strong>“! Er hat die ursprüngliche Nachricht sicher erhalten.&lt;/p>
&lt;hr>
&lt;h2 id="8-wie-man-den-privaten-schlüssel-d-findet-der-erweiterte-euklidische-algorithmus">8. Wie man den privaten Schlüssel $d$ findet: Der erweiterte euklidische Algorithmus
&lt;/h2>&lt;p>Im per Hand berechneten Beispiel haben wir $k$ durch Ausprobieren gesucht, um $d=103$ zu finden, aber wenn die Zahlen Hunderte von Ziffern haben, ist diese Methode unmöglich. In echten Programmen wird ein Algorithmus namens &lt;strong>„erweiterter euklidischer Algorithmus“&lt;/strong> verwendet.&lt;/p>
&lt;p>Die Lösung von $7d \equiv 1 \pmod{120}$ ist gleichbedeutend mit dem Finden der ganzen Zahlen $d$ und $y$, die $7d + 120y = 1$ erfüllen. Durch die Rückwärtsrechnung des euklidischen Algorithmus lässt sich dies maschinell ermitteln.&lt;/p>
&lt;ol>
&lt;li>$120 \div 7 = 17$ Rest $1$&lt;/li>
&lt;li>Durch Umformen ergibt sich: $1 = 120 - 17 \times 7$&lt;/li>
&lt;li>Das heißt: $-17 \times 7 \equiv 1 \pmod{120}$&lt;/li>
&lt;/ol>
&lt;p>$-17$ bedeutet in der Welt von Modulo $120$ dasselbe wie $120 - 17 = 103$. So lässt sich $d = 103$ augenblicklich ermitteln. Diese Methode erlaubt sehr schnelle Berechnungen, egal wie riesig die Zahlen sind.&lt;/p>
&lt;hr>
&lt;h2 id="9-ein-weiteres-gesicht-der-rsa-verschlüsselung-digitale-signaturen">9. Ein weiteres Gesicht der RSA-Verschlüsselung: Digitale Signaturen
&lt;/h2>&lt;p>Das Tolle an der RSA-Verschlüsselung ist, dass sie auch als &lt;strong>„digitale Signatur“&lt;/strong> verwendet werden kann, indem man die Rollen des öffentlichen und privaten Schlüssels vertauscht.&lt;/p>
&lt;p>Während bei der Verschlüsselung das Prinzip „Verschlüsseln mit dem öffentlichen Schlüssel $\Rightarrow$ Entschlüsseln mit dem privaten Schlüssel“ galt,
ist der Ablauf bei der digitalen Signatur „Verschlüsseln mit dem privaten Schlüssel $\Rightarrow$ Entschlüsseln mit dem öffentlichen Schlüssel“.&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Alice erstellt Signatur mit privatem Schlüssel"] --> A2["S ≡ M^d (mod N)"]
A2 --> A3["Sende Nachricht M und Signatur S"]
A3 --> B1["2. Bob verifiziert Signatur mit öffentlichem Schlüssel"]
B1 --> B2["Berechne M' ≡ S^e (mod N)"]
B2 --> B3["Prüfe, ob M' und M übereinstimmen"]&lt;/div>
&lt;p>Alice wandelt die Nachricht mit ihrem eigenen privaten Schlüssel $d$ um (das ist die Signatur $S$) und sendet sie an Bob. Bob führt mit Alices öffentlichem Schlüssel $e$ die Verifizierungsberechnung durch. Wenn das Ergebnis der Berechnung mit der ursprünglichen Nachricht übereinstimmt, beweist dies gleichzeitig, dass „die Daten nur mit Alices privatem Schlüssel erstellt werden konnten“ und dass „die Nachricht unterwegs nicht manipuliert wurde“.&lt;/p>
&lt;hr>
&lt;h2 id="10-die-rsa-verschlüsselung-durch-programmierung-erfahren">10. Die RSA-Verschlüsselung durch Programmierung erfahren
&lt;/h2>&lt;p>Potenzberechnungen, die per Hand extrem mühsam sind, lassen sich in Python sehr einfach implementieren. Im Folgenden finden Sie einen Python-Code, mit dem Sie die Kernlogik der RSA-Verschlüsselung erleben können.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Den größten gemeinsamen Teiler finden&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Den privaten Schlüssel d finden (nutzt die eingebaute Funktion ab Python 3.8)&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Schlüsselerzeugung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">13&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">N&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Öffentlicher Schlüssel: (N=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, e=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">), Privater Schlüssel: d=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Verschlüsselung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">9&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Geheimtext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Entschlüsselung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">decrypted_message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Entschlüsselte Nachricht: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted_message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Die Python-Funktion &lt;code>pow(base, exp, mod)&lt;/code> verwendet intern einen schnellen Algorithmus, der sich „binäre Exponentiation (Square-and-Multiply)“ nennt. Dadurch wird die Berechnung auch bei Zahlen mit Hunderten von Ziffern in einem Augenblick abgeschlossen.&lt;/p>
&lt;hr>
&lt;h2 id="11-zusammenfassung-und-zukünftige-kryptographietechnologien">11. Zusammenfassung und zukünftige Kryptographietechnologien
&lt;/h2>&lt;p>Basierend auf dem Wissen der Schulmathematik haben wir die Funktionsweise der RSA-Verschlüsselung aufgedeckt.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Die Schwierigkeit der Primfaktorzerlegung:&lt;/strong> $p \times q = N$ ist einfach, aber es ist sehr schwer, $p$ und $q$ aus $N$ zu finden.&lt;/li>
&lt;li>&lt;strong>Kongruenzen und der Satz von Euler:&lt;/strong> Das Gesetz $a^{\phi(N)} \equiv 1 \pmod N$ vervollständigt die magische Trapdoor, bei der man „durch Potenzieren mit einer bestimmten Zahl zum Ursprung zurückkehrt“.&lt;/li>
&lt;li>&lt;strong>Öffentlicher und privater Schlüssel:&lt;/strong> Jeder kann verschlüsseln, aber nur der rechtmäßige Empfänger kann entschlüsseln.&lt;/li>
&lt;/ol>
&lt;p>Das $N$ der heute verwendeten RSA-Verschlüsselung hat mehr als 600 Ziffern. Selbst wenn alle Supercomputer der Welt zusammenarbeiten würden, würde die Primfaktorzerlegung länger dauern als das Alter des Universums. Wenn jedoch in Zukunft die derzeit in Entwicklung befindlichen „Quantencomputer“ in die Praxis umgesetzt werden, besteht die Möglichkeit, dass diese Primfaktorzerlegung durch den „Shor-Algorithmus“ augenblicklich geknackt wird. Aus diesem Grund wird derzeit weltweit mit Hochdruck an der Entwicklung der „Post-Quanten-Kryptographie“ gearbeitet, die selbst von Quantencomputern nicht entschlüsselt werden kann.&lt;/p>
&lt;p>Fortgeschrittene Mathematik, die oft als „nutzlos“ abgetan wird, schützt in Wirklichkeit unseren Alltag grundlegend. Die RSA-Verschlüsselung ist das beste Lehrmaterial, um uns diese Tiefe und Schönheit der Mathematik zu zeigen. Ich hoffe, dass Sie durch diesen Artikel ein wenig von der Faszination für Kryptographie und Mathematik spüren konnten.&lt;/p></description></item><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>