<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Math on kenji.blog</title><link>http://kenji.blog/de/tags/math/</link><description>Recent content in Math on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 22:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/math/index.xml" rel="self" type="application/rss+xml"/><item><title>【Für Anfänger】 Die mathematische Struktur des Transformer-Modells entschlüsseln</title><link>http://kenji.blog/de/p/transformer-mathematical-structure/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/de/p/transformer-mathematical-structure/</guid><description>&lt;img src="http://kenji.blog/p/transformer-mathematical-structure/img/eyecatch.jpg" alt="Featured image of post 【Für Anfänger】 Die mathematische Struktur des Transformer-Modells entschlüsseln" />&lt;h1 id="einführung-warum-die-mathematik-des-transformers-lernen">Einführung: Warum die Mathematik des Transformers lernen?
&lt;/h1>&lt;p>Es ist keine Übertreibung zu sagen, dass die Architektur des „Transformers“ die Geschichte der modernen natürlichen Sprachverarbeitung (NLP) und der gesamten KI neu geschrieben hat. Dieses Modell, das erstmals 2017 in dem Paper „Attention Is All You Need“ von Google-Forschern vorgestellt wurde, fungiert als Herzstück der Large Language Models (LLM), die derzeit die Welt dominieren, wie etwa die GPT-Serie von OpenAI (die Basistechnologie von ChatGPT), BERT von Google und Claude von Anthropic.&lt;/p>
&lt;p>Während man oft qualitative Erklärungen zur Funktionsweise des Transformers findet, wie etwa „den Kontext mithilfe des Attention-Mechanismus (Aufmerksamkeitsmechanismus) verstehen“, gibt es überraschenderweise nur wenige tiefgehende Erklärungen der dahinterliegenden &lt;strong>mathematischen Struktur&lt;/strong> für Anfänger. Um wirklich zu verstehen, wie die KI „Wörter“ als „mathematische Formeln“ verarbeitet und erstaunlich natürliche Texte generiert, ist es unerlässlich, ihre mathematischen Mechanismen zu entschlüsseln.&lt;/p>
&lt;p>In diesem Artikel werden wir die mathematischen Strukturen der Kernkomponenten des Transformers, wie den „Self-Attention-Mechanismus“, das „Query-Key-Value (Q/K/V)-Modell“, die „Normalisierung durch die Softmax-Funktion“ und das „Positional Encoding“, für Leser mit Grundkenntnissen in Mathematik und Programmierung (auf dem Niveau von Matrizen und Ableitungen aus der Oberstufe) gründlich und verständlich erläutern.&lt;/p>
&lt;p>Sie könnten von der Aneinanderreihung mathematischer Formeln überwältigt sein, aber jede einzelne Berechnung hat eine klare „Bedeutung“. Wenn Sie diesen Artikel zu Ende gelesen haben, sollten Sie verstehen können, dass der Transformer nicht einfach eine magische Blackbox ist, sondern ein präzise entworfenes Kristall aus Mathematik und Statistik.&lt;/p>
&lt;hr>
&lt;h1 id="1-die-grenzen-herkömmlicher-methoden-und-die-innovation-des-transformers">1. Die Grenzen herkömmlicher Methoden und die Innovation des Transformers
&lt;/h1>&lt;p>Bevor der Transformer aufkam, waren Recurrent Neural Networks (RNN) und ihre Derivate wie LSTM (Long Short-Term Memory) der Mainstream in der natürlichen Sprachverarbeitung. RNNs wurden entwickelt, um Zeitreihendaten zu verarbeiten, und lesen Texte Wort für Wort von Anfang an nacheinander ein.&lt;/p>
&lt;p>RNNs hatten jedoch zwei fatale Schwachstellen:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Schwierigkeiten beim Erlernen langfristiger Abhängigkeiten&lt;/strong>: Wenn Sätze länger werden, verblasst die Information der zuerst eingegebenen Wörter, bis sie das Ende erreichen (Problem des verschwindenden Gradienten).&lt;/li>
&lt;li>&lt;strong>Paralleles Rechnen ist unmöglich&lt;/strong>: Da die Wörter nacheinander verarbeitet werden müssen, sind groß angelegte parallele Berechnungen mithilfe von GPUs schwierig, und das Training nimmt enorm viel Zeit in Anspruch.&lt;/li>
&lt;/ol>
&lt;p>Der Transformer löste einen Paradigmenwechsel aus, indem er die RNN-Struktur komplett verwarf und den Kontext ausschließlich mithilfe von „Attention“ erfasste. Dadurch gibt es unabhängig von der Sequenzlänge keinen Informationsverlust, und Berechnungen können parallelisiert werden, um die Leistung von GPUs maximal auszuschöpfen.&lt;/p>
&lt;hr>
&lt;h1 id="2-die-gesamtarchitektur-des-transformers">2. Die Gesamtarchitektur des Transformers
&lt;/h1>&lt;p>Lassen Sie uns zunächst einen Überblick über die Gesamtarchitektur des Transformers verschaffen. Der Transformer besteht grob aus zwei Blöcken: dem „Encoder“ und dem „Decoder“. Am Beispiel einer Übersetzungsaufgabe wandelt der Encoder die Eingabesprache (z.B. Englisch) in eine mathematische Vektordarstellung um, und der Decoder generiert basierend auf dieser Vektordarstellung die Ausgabesprache (z.B. Japanisch).&lt;/p>
&lt;p>Das folgende Diagramm zeigt vereinfacht die interne Struktur des Encoder-Blocks.&lt;/p>
&lt;div class="mermaid">graph TD
A["Eingabe-Tokens"] --> B["Eingabe-Embedding"]
B --> C["Positional Encoding"]
C --> D["Multi-Head Self-Attention"]
D --> E["Add &amp; Layer Normalization"]
E --> F["Feed-Forward-Netzwerk"]
F --> G["Add &amp; Layer Normalization"]
G --> H["Ausgabe an nächste Schicht"]
C -.->|"Residual Connection"| E
E -.->|"Residual Connection"| G&lt;/div>
&lt;p>Von hier an werden wir die mathematischen Operationen in den einzelnen Komponenten Schritt für Schritt betrachten.&lt;/p>
&lt;hr>
&lt;h1 id="3-vektorisierung-von-wörtern-und-positionskodierung-positional-encoding">3. Vektorisierung von Wörtern und Positionskodierung (Positional Encoding)
&lt;/h1>&lt;p>Computer können Text nicht so verstehen, wie er ist. Der eingegebene Text wird zunächst in Einheiten namens „Tokens“ unterteilt, die jeweils in einen Vektor fester Länge umgewandelt werden. Das ist das &lt;strong>Input Embedding&lt;/strong>.&lt;/p>
&lt;h2 id="31-die-mathematik-des-input-embeddings">3.1 Die Mathematik des Input Embeddings
&lt;/h2>&lt;p>Sei $V$ die Größe des Vokabulars und $d_{model}$ die Anzahl der Dimensionen des Embedding-Vektors (im ursprünglichen Paper war $d_{model} = 512$). Jedes Wort $w_i$ wird mithilfe der Embedding-Matrix $W_E \in \mathbb{R}^{V \times d_{model}}$ in einen Vektor $x_i \in \mathbb{R}^{d_{model}}$ umgewandelt.&lt;/p>
$$ x_i = W_E \cdot \text{one\_hot}(w_i) $$
&lt;p>Dadurch wird der gesamte Satz als Matrix $X \in \mathbb{R}^{N \times d_{model}}$ dargestellt (wobei $N$ die Länge des Satzes ist).&lt;/p>
&lt;h2 id="32-die-notwendigkeit-und-formel-des-positional-encodings">3.2 Die Notwendigkeit und Formel des Positional Encodings
&lt;/h2>&lt;p>Der Transformer verarbeitet Wörter nicht nacheinander wie ein RNN, sondern alle Wörter gleichzeitig und parallel. Dies ist hinsichtlich der Berechnungsgeschwindigkeit ein großer Vorteil, verursacht aber gleichzeitig das Problem, dass &lt;strong>die wichtige Information der „Reihenfolge der Wörter (Wortstellung)“ verloren geht&lt;/strong>. Zum Beispiel sind die eingegebenen Wortmengen für „Ein Hund beißt einen Mann“ und „Ein Mann beißt einen Hund“ identisch, aber die Bedeutung ist völlig unterschiedlich.&lt;/p>
&lt;p>Um dem Modell diese Information über die Wortstellung zur Verfügung zu stellen, wurde das &lt;strong>Positional Encoding&lt;/strong> entwickelt.
Das Positional Encoding $PE$ für die $i$-te Dimension eines Wortes an der Position $pos$ wird mithilfe der folgenden trigonometrischen Funktionen berechnet.&lt;/p>
$$ PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) $$
$$ PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) $$
&lt;p>Hierbei ist $pos$ die Position des Wortes ($0, 1, 2, \dots, N-1$) und $i$ der Index der Dimension des Vektors ($0, 1, \dots, d_{model}/2 - 1$).&lt;/p>
&lt;h3 id="warum-sinus-und-kosinus-verwendet-werden">Warum Sinus und Kosinus verwendet werden
&lt;/h3>&lt;p>Auf den ersten Blick sieht es nach einer sehr komplexen und seltsamen Formel aus, aber es gibt einen tiefen mathematischen Grund dafür. Durch die Verwendung trigonometrischer Funktionen kann das Modell &lt;strong>nicht nur „absolute Positionen“, sondern auch die Differenz „relativer Positionen“&lt;/strong> leicht erlernen.&lt;/p>
&lt;p>Erinnern Sie sich an die Additionstheoreme für trigonometrische Funktionen aus der Schulmathematik.
&lt;/p>
$$ \sin(\alpha + \beta) = \sin\alpha \cos\beta + \cos\alpha \sin\beta $$
$$ \cos(\alpha + \beta) = \cos\alpha \cos\beta - \sin\alpha \sin\beta $$
&lt;p>Das Positional Encoding für eine Position $pos + k$, die um einen Offset $k$ von einer Position $pos$ entfernt ist, kann als Linearkombination des Positional Encodings der Position $pos$ dargestellt werden. Das bedeutet, es kann mithilfe einer Matrix $M_k$ wie folgt geschrieben werden:&lt;/p>
$$ PE_{pos+k} = M_k \cdot PE_{pos} $$
&lt;p>Dadurch kann der Attention-Mechanismus durch die Berechnung von Skalarprodukten leicht erkennen, „wie weit“ Wörter voneinander entfernt sind (relative Distanz). Zudem hat es den Vorteil, dass durch die Kombination mehrerer Sinus- und Kosinuswellen unterschiedlicher Wellenlängen selbst für noch so lange Sätze ein eindeutiger Positionsvektor generiert werden kann.&lt;/p>
&lt;p>Die endgültige Eingabematrix $X_{input}$ ergibt sich aus der Addition der Wort-Embedding-Vektoren und dieses Positional Encodings.&lt;/p>
$$ X_{input} = X + PE $$
&lt;hr>
&lt;h1 id="4-die-tiefgründige-mathematik-der-self-attention-selbstaufmerksamkeitsmechanismus">4. Die tiefgründige Mathematik der Self-Attention (Selbstaufmerksamkeitsmechanismus)
&lt;/h1>&lt;p>Nun dringen wir zur wichtigsten Komponente des Transformers vor: der &lt;strong>Self-Attention (Selbstaufmerksamkeitsmechanismus)&lt;/strong>. Das Ziel der Self-Attention ist es, „die Relevanz aller Wörter in einem Satz untereinander zu berechnen und den Vektor jedes Wortes zu einer reichhaltigeren Darstellung zu aktualisieren, die den Kontext berücksichtigt“.&lt;/p>
&lt;p>Hierbei wird die Analogie eines „Suchsystems“ verwendet.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Query (Q)&lt;/strong>: Suchanfrage. „Nach welchen Informationen suche ich gerade?“&lt;/li>
&lt;li>&lt;strong>Key (K)&lt;/strong>: Schlüssel (Schlagwort). „Welche Informationen habe ich?“&lt;/li>
&lt;li>&lt;strong>Value (V)&lt;/strong>: Wert (Inhalt). „Welche Informationen biete ich tatsächlich an?“&lt;/li>
&lt;/ul>
&lt;h2 id="41-generierung-der-matrizen-q-k-v">4.1 Generierung der Matrizen $Q, K, V$
&lt;/h2>&lt;p>Wir berechnen Query $Q$, Key $K$ und Value $V$, indem wir die Eingabematrix $X \in \mathbb{R}^{N \times d_{model}}$ (zur Vereinfachung ignorieren wir hier die Batch-Größe) mit den lernbaren Gewichtsmatrizen $W^Q, W^K, W^V \in \mathbb{R}^{d_{model} \times d_k}$ multiplizieren. (Normalerweise gilt $d_k = d_v = d_{model} / h$)&lt;/p>
$$ Q = X W^Q $$
$$ K = X W^K $$
$$ V = X W^V $$
&lt;p>Hier sind $Q, K, V$ alle Matrizen der Form $\mathbb{R}^{N \times d_k}$.&lt;/p>
&lt;h2 id="42-berechnung-der-attention-scores-skalarprodukt">4.2 Berechnung der Attention-Scores (Skalarprodukt)
&lt;/h2>&lt;p>Um zu messen, wie stark das Query jedes Wortes mit den Keys aller anderen Wörter in Beziehung steht, berechnen wir das &lt;strong>Skalarprodukt&lt;/strong> der Vektoren. Als Matrixoperation geschrieben, sieht das wie folgt aus:&lt;/p>
$$ \text{Scores} = Q K^T $$
&lt;p>Jedes Element $s_{ij}$ der aus dieser Berechnung resultierenden Matrix $\text{Scores} \in \mathbb{R}^{N \times N}$ repräsentiert das Skalarprodukt zwischen dem Query des $i$-ten Wortes und dem Key des $j$-ten Wortes, d. h. die „Stärke der Relevanz“.&lt;/p>
&lt;h2 id="43-skalierung-scale">4.3 Skalierung (Scale)
&lt;/h2>&lt;p>Die Score-Berechnung durch das Skalarprodukt hat ein Problem. Wenn die Dimension der Vektoren $d_k$ groß wird, werden die Werte des Skalarprodukts extrem groß oder extrem klein.&lt;/p>
&lt;p>Lassen Sie uns dies mathematisch beweisen.
Nehmen wir an, dass jedes Element des Queries $q \sim \mathcal{N}(0, 1)$ und jedes Element des Keys $k \sim \mathcal{N}(0, 1)$ einer unabhängigen Standardnormalverteilung folgt.
Wir bestimmen den Mittelwert und die Varianz des Skalarprodukts $q \cdot k = \sum_{i=1}^{d_k} q_i k_i$.
Mittelwert: Da $\mathbb{E}[q_i k_i] = \mathbb{E}[q_i] \mathbb{E}[k_i] = 0 \times 0 = 0$, ist auch der Mittelwert der Summe $0$.
Varianz: Die Varianz von $q_i k_i$ ist aufgrund der Unabhängigkeit $\text{Var}(q_i k_i) = \mathbb{E}[(q_i k_i)^2] - (\mathbb{E}[q_i k_i])^2 = 1 \times 1 - 0 = 1$.
Daher entspricht die Gesamtvarianz des Skalarprodukts der Dimensionsanzahl $d_k$.&lt;/p>
$$ \text{Var}(q \cdot k) = d_k $$
&lt;p>Wenn die Varianz groß wird, tritt bei der anschließend angewendeten Softmax-Funktion das „Problem des verschwindenden Gradienten“ auf, bei dem die Gradienten für alle Werte außer dem Maximum extrem klein werden, wodurch das Training stagniert.
Um dies zu verhindern, teilen wir die Scores durch $\sqrt{d_k}$ (Skalierung), um die Varianz stets bei $1$ zu halten.&lt;/p>
$$ \text{Scaled Scores} = \frac{Q K^T}{\sqrt{d_k}} $$
&lt;h2 id="44-umwandlung-in-wahrscheinlichkeiten-durch-die-softmax-funktion">4.4 Umwandlung in Wahrscheinlichkeiten durch die Softmax-Funktion
&lt;/h2>&lt;p>Um die erhaltenen Scores in eine Wahrscheinlichkeitsverteilung (Gewichte) umzuwandeln, deren Summe $1$ ergibt, wird die &lt;strong>Softmax-Funktion&lt;/strong> zeilenweise angewendet.&lt;/p>
$$ a_{ij} = \text{softmax}(s_i)_j = \frac{\exp(s_{ij} / \sqrt{d_k})}{\sum_{m=1}^N \exp(s_{im} / \sqrt{d_k})} $$
&lt;p>Die Matrix $A \in \mathbb{R}^{N \times N}$ wird als Attention-Weight-Matrix (Aufmerksamkeitsgewichtsmatrix) bezeichnet. Wenn wir uns jede Zeile $i$ dieser Matrix ansehen, wird durch einen Wert zwischen 0 und 1 ausgedrückt: „Wie viel Aufmerksamkeit (Attention) sollte man anderen Wörtern $j$ schenken, um das Wort $i$ zu verstehen?“.&lt;/p>
&lt;h2 id="45-gewichtete-summe-der-values">4.5 Gewichtete Summe der Values
&lt;/h2>&lt;p>Schließlich berechnen wir mithilfe der erhaltenen Attention-Weight-Matrix $A$ die gewichtete Summe der Value-Matrix $V$.&lt;/p>
$$ \text{Output} = A V = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V $$
&lt;p>Die durch diese Operation ausgegebene Matrix $Z \in \mathbb{R}^{N \times d_v}$ ist eine Sammlung von „Vektordarstellungen der Wörter, die unter Berücksichtigung des Kontextes aktualisiert wurden“.
Dies ist das vollständige Bild der im Paper definierten &lt;strong>Scaled Dot-Product Attention&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="5-multi-head-attention">5. Multi-Head Attention
&lt;/h1>&lt;p>Mit nur einer einzigen Attention-Berechnung (Single-Head) besteht die Möglichkeit, dass der Kontext nur aus einer Perspektive (z. B. „grammatikalische Beziehungen“) erfasst wird. Um die vielfältigen semantischen und syntaktischen Beziehungen der Sprache („Subjekt und Prädikat“, „Pronomen und ihr Bezugswort“ usw.) gleichzeitig zu erfassen, wurde die &lt;strong>Multi-Head Attention&lt;/strong> eingeführt.&lt;/p>
&lt;p>Die Generierung von $Q, K, V$ und die Attention-Berechnung von vorhin werden $h$-mal parallel durchgeführt ($h$ ist die Anzahl der Heads; im ursprünglichen Paper war $h=8$).&lt;/p>
$$ \text{head}_i = \text{Attention}(X W_i^Q, X W_i^K, X W_i^V) $$
&lt;p>Hierbei sind $W_i^Q, W_i^K, W_i^V \in \mathbb{R}^{d_{model} \times d_k}$ die lernbaren Gewichtsmatrizen speziell für den $i$-ten Head.&lt;/p>
&lt;p>Die von jedem Head ausgegebenen Ergebnisse $\text{head}_i \in \mathbb{R}^{N \times d_v}$ werden horizontal verkettet (Concatenate).&lt;/p>
$$ \text{Concat}(\text{head}_1, \dots, \text{head}_h) \in \mathbb{R}^{N \times (h \cdot d_v)} $$
&lt;p>Normalerweise wird $h \cdot d_v = d_{model}$ so gewählt, dass die Dimension nach der Verkettung wieder auf das Eingangsmaß $d_{model}$ zurückkehrt. Schließlich wird diese Matrix mit der Gewichtsmatrix $W^O \in \mathbb{R}^{d_{model} \times d_{model}}$ multipliziert, um die endgültige Ausgabe zu erhalten.&lt;/p>
$$ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W^O $$
&lt;div class="mermaid">graph TD
X["Eingabe X"] --> Q1["Q1"]
X --> K1["K1"]
X --> V1["V1"]
Q1 &amp; K1 &amp; V1 --> H1["Head 1"]
X --> Q2["Q2"]
X --> K2["K2"]
X --> V2["V2"]
Q2 &amp; K2 &amp; V2 --> H2["Head 2"]
X --> QN["..."]
X --> KN["..."]
X --> VN["..."]
QN &amp; KN &amp; VN --> HN["Head h"]
H1 &amp; H2 &amp; HN --> C["Verketten"]
C --> WO["Mit WO multiplizieren"]
WO --> OUT["Multi-Head Ausgabe"]&lt;/div>
&lt;hr>
&lt;h1 id="6-feed-forward-neural-network-ffn">6. Feed-Forward Neural Network (FFN)
&lt;/h1>&lt;p>Die Ausgabe der Multi-Head Attention wird anschließend in das &lt;strong>Position-wise Feed-Forward Network (FFN)&lt;/strong> eingespeist.
Dies ist ein zweischichtiges, vollständig verbundenes neuronales Netzwerk, das „für jede Position (jedes Wort) in der Sequenz unabhängig“ angewendet wird.&lt;/p>
&lt;p>Als mathematische Formel ausgedrückt, sieht das so aus:&lt;/p>
$$ \text{FFN}(x) = \max(0, x W_1 + b_1) W_2 + b_2 $$
&lt;p>Hierbei repräsentiert $\max(0, z)$ die ReLU-Aktivierungsfunktion (Rectified Linear Unit) (in neueren Modellen werden oft auch GELU oder SwiGLU verwendet).&lt;/p>
&lt;p>Die Rolle dieses Netzwerks ist äußerst wichtig. Während der Attention-Mechanismus „Beziehungen zwischen Wörtern (räumliche und sequentielle Beziehungen)“ erlernt, ist das FFN für die „nichtlineare Feature-Transformation jedes einzelnen Wortvektors“ verantwortlich.
Typischerweise wird die Dimension durch die Gewichte der ersten Schicht $W_1$ vorübergehend stark erweitert (z. B. vervierfacht von $d_{model}=512$ auf $d_{ff}=2048$), um komplexe Berechnungen im Merkmalsraum durchzuführen, und dann durch die Gewichte der zweiten Schicht $W_2$ wieder auf die ursprüngliche Dimension reduziert. Durch diese „Erweiterung und Reduktion der Dimensionen“ wird die Ausdruckskraft des Modells dramatisch erhöht.&lt;/p>
&lt;hr>
&lt;h1 id="7-residual-connection-und-layer-normalization">7. Residual Connection und Layer Normalization
&lt;/h1>&lt;p>Im Deep Learning tritt bei tiefer werdenden Netzwerkschichten das Problem auf, dass Gradienten während des Trainings verschwinden oder explodieren, was ein erfolgreiches Training verhindert. Um dies zu verhindern, sind um jede Subschicht (Attention und FFN) des Transformers eine &lt;strong>Residual Connection (Restverbindung)&lt;/strong> und eine &lt;strong>Layer Normalization (Schichtnormalisierung)&lt;/strong> angeordnet.&lt;/p>
&lt;p>Als Formel geschrieben, wird die Ausgabe der Subschicht wie folgt verarbeitet:&lt;/p>
$$ \text{Output} = \text{LayerNorm}(x + \text{Sublayer}(x)) $$
&lt;h2 id="71-residual-connection-x--textsublayerx">7.1 Residual Connection ($x + \text{Sublayer}(x)$)
&lt;/h2>&lt;p>Die Eingabe $x$ wird direkt zur Ausgabe der Subschicht addiert. Dadurch wird der Gradient bei der Backpropagation direkt durch einen Shortcut in flachere Schichten weitergeleitet, wodurch das Training selbst bei tiefen Schichten stabil bleibt.&lt;/p>
&lt;h2 id="72-die-mathematik-der-layer-normalization">7.2 Die Mathematik der Layer Normalization
&lt;/h2>&lt;p>Layer Normalization ist eine Technik, die den Mittelwert und die Varianz entlang der Dimension der Merkmale berechnet und die Daten normalisiert. Bei einer Eingabe mit der Batch-Größe $B$, der Sequenzlänge $N$ und der Dimensionsanzahl $d_{model}$ wird die Normalisierung für einen einzelnen Wortvektor $x \in \mathbb{R}^{d_{model}}$ durchgeführt.&lt;/p>
&lt;p>Wir berechnen den Mittelwert $\mu$ und die Varianz $\sigma^2$.
&lt;/p>
$$ \mu = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} x_i $$
$$ \sigma^2 = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} (x_i - \mu)^2 $$
&lt;p>Dann erhalten wir die normalisierte Ausgabe $\hat{x}$.
&lt;/p>
$$ \text{LN}(x) = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} \odot \gamma + \beta $$
&lt;p>
($\epsilon$ ist eine winzige Konstante zur Vermeidung einer Division durch null. $\gamma, \beta$ sind lernbare Skalierungs- und Verschiebungsparameter.)&lt;/p>
&lt;p>Der Grund für die Verwendung der schichtweisen Normalisierung (Layer Normalization) anstelle der Normalisierung in Batch-Richtung (Batch Normalization) liegt darin, dass bei der Verarbeitung von sequenziellen Daten mit variabler Länge, wie z.B. Sätzen, die Statistiken zwischen den Batches tendenziell instabil werden. Dank der Layer Normalization ermöglicht der Transformer ein stabiles Training unabhängig von der Batch-Größe.&lt;/p>
&lt;hr>
&lt;h1 id="8-decoderspezifische-strukturen-masked-attention-und-cross-attention">8. Decoderspezifische Strukturen: Masked Attention und Cross-Attention
&lt;/h1>&lt;p>Die bisher erläuterten Strukturen gehören zum Encoder. Beim Decoder-Block, der Sätze generiert, weicht die Struktur leicht ab.&lt;/p>
&lt;h2 id="81-masked-multi-head-attention">8.1 Masked Multi-Head Attention
&lt;/h2>&lt;p>Die Rolle des Decoders ist es, „das nächste Wort aus vergangenen Wörtern vorherzusagen“. Daher wäre es beim Training Schummeln, wenn er „zukünftige Wörter“ sehen würde. Die mathematische Operation, um dies zu verhindern, ist das &lt;strong>Masking (Maskierung)&lt;/strong>.&lt;/p>
&lt;p>Zur Score-Matrix $Q K^T$ wird eine Maskenmatrix $M$ addiert, die im oberen Dreiecksteil (was den zukünftigen Informationen entspricht) sehr kleine Werte nahe $-\infty$ setzt.&lt;/p>
$$ M_{ij} = \begin{cases} 0 &amp; (i \le j) \\ -\infty &amp; (i > j) \end{cases} $$
$$ \text{Masked Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T + M}{\sqrt{d_k}}\right) V $$
&lt;p>Bei der Berechnung der Softmax-Funktion wird $\exp(-\infty) = 0$, sodass das Attention-Weight für zukünftige Wörter komplett $0$ wird. Dadurch wird eine autoregressive Generierung unter Beibehaltung der Kausalität ermöglicht.&lt;/p>
&lt;h2 id="82-encoder-decoder-cross-attention">8.2 Encoder-Decoder Cross-Attention
&lt;/h2>&lt;p>Die zweite Subschicht des Decoders ist die &lt;strong>Cross-Attention&lt;/strong>, die auf die Ausgabe des Encoders verweist.
Hierbei wird $Q$ aus der vorherigen Decoder-Schicht generiert, während $K$ und $V$ aus der Ausgabe der letzten Encoder-Schicht generiert werden.&lt;/p>
$$ Q_{decoder} = X_{dec} W^Q $$
$$ K_{encoder} = X_{enc} W^K $$
$$ V_{encoder} = X_{enc} W^V $$
&lt;p>Durch diese Berechnung kann das Modell bei Übersetzungsaufgaben lernen, „mit welchem Teil des ursprünglichen fremdsprachigen Satzes das aktuell zu übersetzende Wort stark zusammenhängt“.&lt;/p>
&lt;hr>
&lt;h1 id="9-rechenaufwand-und-die-mathematik-der-optimierung-in-der-moderne">9. Rechenaufwand und die Mathematik der Optimierung in der Moderne
&lt;/h1>&lt;p>Der Transformer ist ein großartiges Modell, hat aber aufgrund seiner mathematischen Struktur auch „Schwachstellen“.
Achten Sie auf den Rechenaufwand der Self-Attention. Bei der Berechnung der Score-Matrix $Q K^T$ wird eine $(N \times d_k)$-Matrix mit einer $(d_k \times N)$-Matrix multipliziert, sodass der Rechenaufwand &lt;strong>$O(N^2 \cdot d_{model})$&lt;/strong> beträgt.&lt;/p>
&lt;p>Das bedeutet, dass &lt;strong>Rechenaufwand und Speicherverbrauch quadratisch zur Sequenzlänge $N$ ansteigen&lt;/strong>.
Bei kurzen Texten ist das kein Problem, aber wenn man versucht, einen extrem langen Kontext wie ein ganzes Buch in ein LLM einzuspeisen, erreicht $N$ Zehn- bis Hunderttausende, und bei herkömmlichen Attention-Berechnungen wäre der GPU-Speicher sofort erschöpft.&lt;/p>
&lt;p>Um diesen Fluch der $O(N^2)$-Komplexität zu brechen, wurden in den letzten Jahren verschiedene Optimierungen aus mathematischen und hardwaretechnischen Ansätzen vorgeschlagen.
Ein Paradebeispiel dafür ist &lt;strong>FlashAttention&lt;/strong>. FlashAttention ist ein Algorithmus, der die Attention-Berechnung in Kacheln unterteilt (Tiling), um den Datentransfer (Speicherzugriff) zwischen den Speicherhierarchien der GPU (SRAM und HBM) zu minimieren. Obwohl es mathematisch exakt das gleiche Ergebnis wie die Standard-Attention liefert (Exact Attention), erreicht es durch Optimierung auf Hardware-Ebene eine dramatische Beschleunigung und Speicherreduzierung, was die Realisierung von Modellen mit langem Kontext wie GPT-4 ermöglicht hat.&lt;/p>
&lt;p>Darüber hinaus wird intensiv an Sparse Attention, Linear Attention und Ähnlichem geforscht, die den Rechenaufwand auf $O(N \log N)$ oder $O(N)$ annähern.&lt;/p>
&lt;hr>
&lt;h1 id="10-vorstellungen-zur-implementierung-pseudocode-im-pytorch-stil">10. Vorstellungen zur Implementierung (Pseudocode im PyTorch-Stil)
&lt;/h1>&lt;p>Wenn man die bisherigen mathematischen Strukturen in tatsächlichen Programmiercode (Python / PyTorch) überträgt, stellt man fest, dass sie überraschend einfach geschrieben werden können. Hier ist der Pseudocode für den Kernteil der Self-Attention.&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&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">torch.nn.functional&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">F&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">math&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">scaled_dot_product_attention&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">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">mask&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Form von q, k, v: [batch_size, num_heads, seq_length, d_k]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d_k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. Score-Berechnung durch Skalarprodukt: Q * K^T&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Die letzten beiden Dimensionen transponieren und Matrixprodukt berechnen&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">matmul&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">k&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">transpose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. Skalierung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">scores&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_k&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. Maskierung (im Falle von Masked Attention)&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">mask&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">scores&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">masked_fill&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mask&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mf">1e9&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"># 4. Umwandlung in Wahrscheinlichkeiten durch Softmax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attention_weights&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">F&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">scores&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. Multiplikation mit der Value-Matrix&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">matmul&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attention_weights&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&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">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attention_weights&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Man kann sehen, dass der mathematisch dargestellte Ausdruck $Q K^T / \sqrt{d_k}$ intuitiv als &lt;code>torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)&lt;/code> implementiert wird. Es ist ein sehr faszinierender Aspekt des Deep Learning, dass mathematische Theorien mithilfe von stark optimierten Bibliotheken in wenigen Codezeilen realisiert werden können.&lt;/p>
&lt;hr>
&lt;h1 id="fazit-die-form-der-intelligenz-wie-sie-aus-mathematischen-formeln-ersichtlich-wird">Fazit: Die Form der „Intelligenz“, wie sie aus mathematischen Formeln ersichtlich wird
&lt;/h1>&lt;p>In diesem Artikel haben wir die tiefgründigen mathematischen Strukturen des Transformer-Modells entschlüsselt.&lt;/p>
&lt;p>Das Embedding, das Wörter in einen mehrdimensionalen Vektorraum abbildet, das Positional Encoding, das Positionsinformationen durch die Synthese von Dreieckswellen ausdrückt, und der Self-Attention-Mechanismus, der aus einer Analogie zur Informationsbeschaffung entstandene Matrizenmultiplikationen verwendet. Jede dieser Komponenten ist lediglich eine Ansammlung von grundlegender Mathematik wie linearer Algebra, Differenzial- und Integralrechnung sowie Wahrscheinlichkeitsrechnung und Statistik.&lt;/p>
&lt;p>Wenn sich diese einfachen Matrixoperationen jedoch in unzähligen Schichten überlagern und Muster aus gigantischen Datensätzen durch Milliarden oder Hunderte von Milliarden an Parametern lernen, entsteht eine „Form von Intelligenz“, die unsere „Wörter“ zu verstehen, logische Schlüsse zu ziehen und manchmal kreative Ideen hervorzubringen scheint.&lt;/p>
&lt;p>Wie der provokante Titel „Attention Is All You Need“ andeutet, liegt die Schönheit dieser Architektur, die komplexe rekurrente und konvolutionale Verarbeitungen verworfen und sich auf die reinrassige Berechnung von „Attention (Relevanz)“ spezialisiert hat, gerade in ihrer mathematischen Einfachheit.&lt;/p>
&lt;p>In Zukunft könnten zwar neue Architekturen auftauchen, die den Transformer übertreffen (wie z. B. Mamba, ein State Space Model), aber der mathematische Rahmen des „Kontextverständnisses durch Attention“, den der Transformer geschaffen hat, wird für immer in der Geschichte der KI verankert bleiben.&lt;/p>
&lt;p>Wenn Sie künftig die Gelegenheit haben, LLMs wie ChatGPT oder Claude zu nutzen, stellen Sie sich vor, wie im Hintergrund jede Sekunde Billionen von Matrixmultiplikationen von $Q K^T$ berechnet werden und die Softmax-Funktion Wahrscheinlichkeiten ausspuckt. Ihr Verständnis für die Technologie wird sich vertiefen, und die Welt der KI wird Ihnen noch faszinierender erscheinen.&lt;/p>
&lt;h3 id="literaturverzeichnis">Literaturverzeichnis
&lt;/h3>&lt;ul>
&lt;li>Vaswani, A., et al. (2017). &amp;ldquo;Attention Is All You Need.&amp;rdquo; &lt;em>Advances in Neural Information Processing Systems&lt;/em>.&lt;/li>
&lt;li>Alammar, J. (2018). &amp;ldquo;The Illustrated Transformer.&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>&lt;em>Dieser Artikel wurde als Leitfaden für all jene verfasst, die die mathematischen Grundlagen der natürlichen Sprachverarbeitung und der KI erlernen möchten. Wenn Sie Fragen oder Diskussionsbedarf haben, lassen Sie es mich bitte in den Kommentaren wissen!&lt;/em>&lt;/p></description></item><item><title>Grundlagen und Implementierung der Verschlüsselung mit dem kleinen Satz von Fermat</title><link>http://kenji.blog/de/p/fermats-little-theorem-cryptography-implementation/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/de/p/fermats-little-theorem-cryptography-implementation/</guid><description>&lt;img src="http://kenji.blog/p/fermats-little-theorem-cryptography-implementation/img/eyecatch.jpg" alt="Featured image of post Grundlagen und Implementierung der Verschlüsselung mit dem kleinen Satz von Fermat" />&lt;h2 id="1-einführung-das-geheimnis-der-mathematik-hinter-der-modernen-kryptographie">1. Einführung: Das Geheimnis der Mathematik hinter der modernen Kryptographie
&lt;/h2>&lt;p>In der modernen digitalen Gesellschaft, insbesondere bei der Kommunikation über das Internet, ist &amp;ldquo;Verschlüsselung&amp;rdquo; zu einer unverzichtbaren Basistechnologie geworden. Dass wir Websites über HTTPS sicher in einem Webbrowser durchsuchen, Finanztransaktionen im Online-Banking durchführen und privat in Messaging-Apps kommunizieren können, liegt daran, dass kryptographische Protokolle, die durch fortgeschrittene mathematische Theorien gestützt werden, im Hintergrund arbeiten. Eine besonders wichtige Rolle spielt dabei die &amp;ldquo;Public-Key-Kryptographie&amp;rdquo;, deren prominentester Vertreter die &lt;strong>RSA-Verschlüsselung&lt;/strong> ist.&lt;/p>
&lt;p>Die Sicherheit und Gültigkeit vieler kryptographischer Algorithmen, einschließlich RSA, hängt stark von einem sehr schönen und mächtigen Satz ab, der im 17. Jahrhundert vom französischen Mathematiker Pierre de Fermat entdeckt wurde. Das ist der &lt;strong>kleine Satz von Fermat&lt;/strong>. Darüber hinaus spielt der Satz von Leonhard Euler, der diesen verallgemeinert, eine entscheidende Rolle in der Kryptographietheorie.&lt;/p>
&lt;p>In diesem Artikel werden wir von Grund auf ausführlich erklären, wie die Entdeckung der reinen Mathematik, der kleine Satz von Fermat, in der modernen, praktischen Kryptographie, insbesondere beim &amp;ldquo;Primzahltest&amp;rdquo; und bei der &amp;ldquo;RSA-Verschlüsselung&amp;rdquo;, Anwendung findet. Dies ist ein sehr detaillierter technischer Leitfaden, der mathematische Beweise, Ver- und Entschlüsselungsmechanismen sowie spezifische Algorithmus-Implementierungen in C++ und Python abdeckt.&lt;/p>
&lt;hr>
&lt;h2 id="2-grundlagen-der-kongruenzen-und-der-modularen-arithmetik">2. Grundlagen der Kongruenzen und der modularen Arithmetik
&lt;/h2>&lt;p>Um den kleinen Satz von Fermat zu verstehen, müssen wir uns zunächst mit dem mathematischen Konzept der &amp;ldquo;modularen Arithmetik (Kongruenz)&amp;rdquo; vertraut machen. Die modulare Arithmetik ist ein Rechensystem, das sich auf den &amp;ldquo;Rest&amp;rdquo; nach der Division durch eine bestimmte feste Zahl (Modul genannt) konzentriert. Da es sich um eine Berechnung wie beim Zifferblatt einer Uhr (die in 12 Stunden einen Umlauf macht) handelt, wird sie auch &amp;ldquo;Uhrenarithmetik&amp;rdquo; genannt.&lt;/p>
&lt;p>Wenn die Reste der Division der ganzen Zahlen $a$ und $b$ durch eine positive ganze Zahl $n$ gleich sind, wird dies mathematisch wie folgt beschrieben:&lt;/p>
$$
a \equiv b \pmod n
$$
&lt;p>Dies liest sich als &amp;ldquo;$a$ und $b$ sind kongruent modulo $n$&amp;rdquo;. Zum Beispiel ist der Rest von 17 geteilt durch 5 gleich 2, und der Rest von 12 geteilt durch 5 ist ebenfalls 2. Daher können wir schreiben:&lt;/p>
$$
17 \equiv 12 \pmod 5 \equiv 2 \pmod 5
$$
&lt;p>In der modularen Arithmetik gelten die üblichen vier Grundrechenarten (Addition, Subtraktion, Multiplikation) wie gewohnt:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition&lt;/strong>: Wenn $a \equiv b \pmod n$ und $c \equiv d \pmod n$, dann $a + c \equiv b + d \pmod n$&lt;/li>
&lt;li>&lt;strong>Subtraktion&lt;/strong>: Wenn $a \equiv b \pmod n$ und $c \equiv d \pmod n$, dann $a - c \equiv b - d \pmod n$&lt;/li>
&lt;li>&lt;strong>Multiplikation&lt;/strong>: Wenn $a \equiv b \pmod n$ und $c \equiv d \pmod n$, dann $a \times c \equiv b \times d \pmod n$&lt;/li>
&lt;li>&lt;strong>Potenzieren&lt;/strong>: Wenn $a \equiv b \pmod n$, dann $a^k \equiv b^k \pmod n$ für jede natürliche Zahl $k$&lt;/li>
&lt;/ol>
&lt;p>Bei der &lt;strong>Division&lt;/strong> ist jedoch Vorsicht geboten. Im Allgemeinen bedeutet $a \times c \equiv b \times c \pmod n$ nicht, dass wir beide Seiten durch $c$ teilen und $a \equiv b \pmod n$ erhalten können. Dies gilt nur, wenn $c$ und $n$ teilerfremd sind (ihr größter gemeinsamer Teiler ist 1). Dieses Konzept des &amp;ldquo;modularen Inversen&amp;rdquo; ist extrem wichtig bei der Schlüsselgenerierung der RSA-Verschlüsselung, die später beschrieben wird.&lt;/p>
&lt;hr>
&lt;h2 id="3-mathematischer-hintergrund-und-beweis-des-kleinen-satzes-von-fermat">3. Mathematischer Hintergrund und Beweis des kleinen Satzes von Fermat
&lt;/h2>&lt;p>Nachdem wir nun die Grundlagen der modularen Arithmetik behandelt haben, kommen wir zum Hauptthema: dem kleinen Satz von Fermat.&lt;/p>
&lt;h3 id="31-definition-des-satzes">3.1 Definition des Satzes
&lt;/h3>&lt;p>Der kleine Satz von Fermat wird wie folgt formuliert:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Kleiner Satz von Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>
Sei $p$ eine Primzahl und $a$ eine beliebige ganze Zahl, die kein Vielfaches von $p$ ist (d.h. $a$ und $p$ sind teilerfremd). Dann gilt die folgende Kongruenz:
&lt;/p>
$$ a^{p-1} \equiv 1 \pmod p $$
&lt;/blockquote>
&lt;p>Es ist auch üblich, die Bedingung &amp;ldquo;$a$ ist kein Vielfaches von $p$&amp;rdquo; zu entfernen und es so auszudrücken, dass es für alle ganzen Zahlen $a$ gilt. In diesem Fall multiplizieren wir beide Seiten mit $a$ und erhalten:&lt;/p>
$$
a^p \equiv a \pmod p
$$
&lt;h3 id="32-bestätigung-durch-konkrete-beispiele">3.2 Bestätigung durch konkrete Beispiele
&lt;/h3>&lt;p>Lassen Sie uns anhand konkreter Zahlen prüfen, ob der Satz wirklich gilt.
Sei die Primzahl $p = 5$. Dann ist $p-1 = 4$. Wir wählen als $a$ ganze Zahlen, die keine Vielfachen von $p$ sind.&lt;/p>
&lt;ul>
&lt;li>Für $a = 2$: $2^{5-1} = 2^4 = 16$. $16 \div 5 = 3$ Rest $1$. Also $16 \equiv 1 \pmod 5$. (Gültig)&lt;/li>
&lt;li>Für $a = 3$: $3^{5-1} = 3^4 = 81$. $81 \div 5 = 16$ Rest $1$. Also $81 \equiv 1 \pmod 5$. (Gültig)&lt;/li>
&lt;li>Für $a = 4$: $4^{5-1} = 4^4 = 256$. $256 \div 5 = 51$ Rest $1$. Also $256 \equiv 1 \pmod 5$. (Gültig)&lt;/li>
&lt;/ul>
&lt;p>Wie Sie sehen können, egal welches $a$ Sie wählen (solange es kein Vielfaches von 5 ist), ist der Rest immer 1, wenn Sie es zur 4. Potenz erheben und durch 5 teilen. Es scheint wie Magie, aber es stammt von den wunderbaren Eigenschaften der Primzahlen ab.&lt;/p>
&lt;h3 id="33-mathematischer-beweis-des-satzes">3.3 Mathematischer Beweis des Satzes
&lt;/h3>&lt;p>Warum ist das so? Hier stellen wir einen eleganten Beweis mit Hilfe der Menge der Restklassen vor.&lt;/p>
&lt;p>Betrachten wir die Menge $S = \{1, 2, 3, \dots, p-1\}$. Dies sind Repräsentanten der ganzen Zahlen, deren Rest bei Division durch $p$ von $1$ bis $p-1$ reicht.
Betrachten wir nun eine neue Menge $T$, in der jedes Element mit einer zu $p$ teilerfremden ganzen Zahl $a$ multipliziert wird.
&lt;/p>
$$ T = \{1a, 2a, 3a, \dots, (p-1)a\} $$
&lt;p>Betrachten wir den Rest jedes Elements dieser Menge $T$ bei der Division durch $p$. Erstaunlicherweise stimmen diese Reste – obwohl ihre Reihenfolge vertauscht sein mag – genau mit der Menge der Elemente der ursprünglichen Menge $S$ überein.
Weil:&lt;/p>
&lt;ol>
&lt;li>Kein Element von $T$ ein Vielfaches von $p$ wird (da weder $a$ noch die ursprünglichen Elemente Vielfache von $p$ sind).&lt;/li>
&lt;li>Es in $T$ keine zwei verschiedenen Elemente gibt, die modulo $p$ kongruent sind. Wenn $ia \equiv ja \pmod p$ ($i \neq j$) wäre, könnten wir durch $a$ teilen, da $a$ und $p$ teilerfremd sind, und bekämen $i \equiv j \pmod p$, was ein Widerspruch ist.&lt;/li>
&lt;/ol>
&lt;p>Daher ist das Produkt aller Elemente von $S$ kongruent zum Produkt aller Elemente von $T$ modulo $p$.&lt;/p>
$$
(1a) \times (2a) \times \dots \times ((p-1)a) \equiv 1 \times 2 \times \dots \times (p-1) \pmod p
$$
&lt;p>Wenn wir die linke Seite umstellen, haben wir $p-1$ mal $a$, also:&lt;/p>
$$
a^{p-1} \cdot (p-1)! \equiv (p-1)! \pmod p
$$
&lt;p>Da $(p-1)!$ teilerfremd zu $p$ ist, können wir beide Seiten durch $(p-1)!$ teilen und erhalten schließlich den folgenden Satz:&lt;/p>
$$
a^{p-1} \equiv 1 \pmod p
$$
&lt;p>Dies ist der Beweis für den kleinen Satz von Fermat.&lt;/p>
&lt;hr>
&lt;h2 id="4-eulersche-phi-funktion-und-der-satz-von-euler">4. Eulersche Phi-Funktion und der Satz von Euler
&lt;/h2>&lt;p>Der kleine Satz von Fermat ist ein Satz über &amp;ldquo;Primzahlen $p$&amp;rdquo;, aber Leonhard Euler verallgemeinerte ihn für &amp;ldquo;beliebige positive ganze Zahlen $n$&amp;rdquo;. Diese Erweiterung ist entscheidend, um die RSA-Verschlüsselung zu verstehen.&lt;/p>
&lt;h3 id="41-die-eulersche-phi-funktion-phin">4.1 Die Eulersche Phi-Funktion $\phi(n)$
&lt;/h3>&lt;p>Die Eulersche Phi-Funktion (oder Eulersche Totientenfunktion) $\phi(n)$ ist eine Funktion, die die &amp;ldquo;Anzahl der ganzen Zahlen von $1$ bis $n$, die teilerfremd zu $n$ sind&amp;rdquo;, angibt.&lt;/p>
&lt;ul>
&lt;li>Für eine Primzahl $p$ sind alle ganzen Zahlen von $1$ bis $p-1$ teilerfremd zu $p$, also ist $\phi(p) = p - 1$.&lt;/li>
&lt;li>Für zwei verschiedene Primzahlen $p$ und $q$ und deren Produkt $n = p \times q$ kann $\phi(n)$ mit einer sehr einfachen Formel berechnet werden:
$$ \phi(p \times q) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$&lt;/li>
&lt;/ul>
&lt;p>Diese Eigenschaft ist die Kernlogik bei der Schlüsselgenerierung für die RSA-Verschlüsselung.&lt;/p>
&lt;h3 id="42-der-satz-von-euler">4.2 Der Satz von Euler
&lt;/h3>&lt;p>Euler verallgemeinerte den kleinen Satz von Fermat wie folgt:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Satz von Euler (Euler&amp;rsquo;s Theorem)&lt;/strong>
Für eine positive ganze Zahl $n$ und eine zu ihr teilerfremde ganze Zahl $a$ gilt:
&lt;/p>
$$ a^{\phi(n)} \equiv 1 \pmod n $$
&lt;/blockquote>
&lt;p>Wenn $n$ eine Primzahl $p$ ist, dann ist $\phi(p) = p - 1$, also ist dies genau der kleine Satz von Fermat ($a^{p-1} \equiv 1 \pmod p$). Der kleine Satz von Fermat ist also nur ein Spezialfall des Satzes von Euler.&lt;/p>
&lt;hr>
&lt;h2 id="5-riesige-primzahlen-finden-der-fermat-primzahltest">5. Riesige Primzahlen finden: Der Fermat-Primzahltest
&lt;/h2>&lt;p>In der Kryptographie (wie bei der RSA-Verschlüsselung und dem Diffie-Hellman-Schlüsselaustausch) ist es notwendig, schnell &amp;ldquo;riesige Primzahlen&amp;rdquo; mit hunderten von Ziffern zu finden. Um jedoch zu testen, ob eine riesige Zahl $N$ prim ist, würde die Methode der &amp;ldquo;Probedivision&amp;rdquo;, bei der man versucht, durch alle Zahlen von $2$ bis $\sqrt{N}$ zu teilen, etwa so lange dauern wie das Alter des Universums.&lt;/p>
&lt;p>Hier kommt der &lt;strong>Fermat-Primzahltest (Fermat Primality Test)&lt;/strong> ins Spiel, ein &amp;ldquo;probabilistischer Primzahltest&amp;rdquo;, der den kleinen Satz von Fermat umkehrt.&lt;/p>
&lt;h3 id="51-was-ist-ein-probabilistischer-primzahltest">5.1 Was ist ein probabilistischer Primzahltest?
&lt;/h3>&lt;p>Nach dem kleinen Satz von Fermat gilt, wenn $p$ eine Primzahl ist, für jedes $a$ ($1 &lt; a &lt; p$) immer $a^{p-1} \equiv 1 \pmod p$.
Wenn wir die Kontraposition davon nehmen, können wir sagen: &amp;ldquo;Wenn es ein $a$ gibt, für das $a^{p-1} \not\equiv 1 \pmod p$ ist, dann ist $p$ &lt;strong>absolut keine Primzahl (es ist eine zusammengesetzte Zahl)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>Wenn wir also testen wollen, ob $N$ prim ist, wählen wir zufällig einige $a$ und berechnen $a^{N-1} \pmod N$, um zu sehen, ob das Ergebnis $1$ ist. Wenn wir auch nur einmal ein anderes Ergebnis als $1$ erhalten, ist mit Sicherheit bestätigt, dass $N$ eine zusammengesetzte Zahl ist. Wenn das Ergebnis nach vielen Versuchen immer $1$ ist, können wir mit hoher Wahrscheinlichkeit schlussfolgern, dass $N$ &amp;ldquo;wahrscheinlich eine Primzahl ist&amp;rdquo;.&lt;/p>
&lt;h3 id="52-erklärung-des-algorithmus-und-flussdiagramm">5.2 Erklärung des Algorithmus und Flussdiagramm
&lt;/h3>&lt;p>Der Algorithmus für den Fermat-Test ist wie folgt:&lt;/p>
&lt;div class="mermaid">flowchart TD
Start["Start"] --> Input["Zahl p zum Testen und Anzahl der Tests k eingeben"]
Input --> LoopStart["Schleife von i = 0 bis k-1"]
LoopStart --> Condition{"i &lt; k ?"}
Condition -- "Ja" --> RandomA["Wähle zufällige ganze Zahl a im Bereich 1 &lt; a &lt; p-1"]
RandomA --> Calc["Berechne modulares Potenzieren a^(p-1) mod p"]
Calc --> CheckPrime{"Ist das Ergebnis 1?"}
CheckPrime -- "Nein" --> ReturnComposite["p ist eine zusammengesetzte Zahl (bestätigt)"]
CheckPrime -- "Ja" --> Increment["Erhöhe i"]
Increment --> Condition
Condition -- "Nein" --> ReturnPrime["p ist wahrscheinlich eine Primzahl (probabilistisch)"]
ReturnComposite --> End["Ende"]
ReturnPrime --> End&lt;/div>
&lt;h3 id="53-die-falle-der-carmichael-zahlen-pseudoprimzahlen">5.3 Die Falle der Carmichael-Zahlen (Pseudoprimzahlen)
&lt;/h3>&lt;p>Der Fermat-Test ist sehr schnell, hat aber einen großen Fehler. Es gibt teuflische Zahlen, die zusammengesetzt sind, aber dennoch $a^{N-1} \equiv 1 \pmod N$ für alle $a$ erfüllen. Diese werden &lt;strong>Carmichael-Zahlen (Carmichael numbers)&lt;/strong> genannt. Die kleinste Carmichael-Zahl ist $561$ ($3 \times 11 \times 17$).&lt;/p>
&lt;p>Aufgrund der Existenz von Carmichael-Zahlen kann ein reiner Fermat-Test allein keinen absoluten Primzahltest garantieren. Daher verwenden reale Verschlüsselungssysteme (wie OpenSSL) standardmäßig den &lt;strong>Miller-Rabin-Primzahltest&lt;/strong>, der eine Verbesserung des Fermat-Tests darstellt. Der Miller-Rabin-Test kann Carmichael-Zahlen erkennen, wodurch die Wahrscheinlichkeit eines falschen Ergebnisses praktisch auf Null reduziert wird.&lt;/p>
&lt;h3 id="54-schnelles-modulares-potenzieren-binäre-exponentiation">5.4 Schnelles modulares Potenzieren (Binäre Exponentiation)
&lt;/h3>&lt;p>Im Primzahltestalgorithmus müssen wir $a^{N-1} \pmod N$ berechnen. Wenn $N$ riesig ist, hat $a^{N-1}$ eine astronomische Anzahl von Ziffern und passt nicht in den Speicher des Computers.
Die Lösung dafür ist die &lt;strong>binäre Exponentiation (Exponentiation by Squaring)&lt;/strong> oder das modulare Potenzieren. Durch das Modulo (mod N) bei jedem Schritt der Berechnung wird der Wert immer kleiner als $N$ gehalten, und die Berechnung wird sehr schnell möglich (Zeitkomplexität $O(\log N)$).&lt;/p>
&lt;hr>
&lt;h2 id="6-implementierung-von-primzahltest-und-modularem-potenzieren">6. Implementierung von Primzahltest und modularem Potenzieren
&lt;/h2>&lt;p>Lassen Sie uns nun den Fermat-Primzahltest und die binäre Exponentiation in C++ und Python implementieren.&lt;/p>
&lt;h3 id="61-implementierung-in-c">6.1 Implementierung in C++
&lt;/h3>&lt;p>In C++ laufen Standard-Ganzzahltypen leicht über, daher ist eine Big-Integer-Bibliothek (wie GMP) erforderlich, um riesige Zahlen zu handhaben. Aber hier zeigen wir eine Implementierung innerhalb des Bereichs von 64-Bit-Ganzzahlen (&lt;code>unsigned long long&lt;/code>), um den Algorithmus zu verstehen.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;random&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Schnelles modulares Potenzieren (a^b mod m) - Binäre Exponentiation
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Wenn das niedrigstwertige Bit von b 1 ist, multipliziere das Ergebnis mit a
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 128-Bit-Erweiterung zur Vermeidung von Überlauf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// a quadrieren
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// b nach rechts verschieben (halbieren)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Fermat-Primzahltest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">bool&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">iterations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">random_device&lt;/span> &lt;span class="n">rd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mt19937_64&lt;/span> &lt;span class="n">gen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rd&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uniform_int_distribution&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gen&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Wenn a^(p-1) mod p nicht 1 ist, ist es eine zusammengesetzte Zahl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Wahrscheinlich prim
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000000007&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Bekannte Primzahl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is probably prime.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is composite.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-implementierung-in-python">6.2 Implementierung in Python
&lt;/h3>&lt;p>Der Standard-Ganzzahltyp von Python unterstützt beliebig große Zahlen, sodass Sie sich keine Sorgen über einen Überlauf machen müssen. Darüber hinaus verwendet die in Python integrierte Funktion &lt;code>pow(a, b, m)&lt;/code> intern die binäre Exponentiation und ist sehr schnell.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Probabilistischer Primzahltest unter Verwendung des Fermat-Primzahltests
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Wähle eine zufällige Zahl a zwischen 2 und p-2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Berechne a^(p-1) mod p. Das integrierte pow ist schnell.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># Bestätigt zusammengesetzt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span> &lt;span class="c1"># Wahrscheinlich prim&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">number_to_test&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">104729&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> ist wahrscheinlich prim.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> ist zusammengesetzt.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-anwendung-auf-die-rsa-verschlüsselung-wo-fermat-und-euler-zusammenkommen">7. Anwendung auf die RSA-Verschlüsselung: Wo Fermat und Euler zusammenkommen
&lt;/h2>&lt;p>Die großartigste Anwendung des kleinen Satzes von Fermat (und des Satzes von Euler) ist die &lt;strong>RSA-Verschlüsselung&lt;/strong>, die 1977 von Rivest, Shamir und Adleman entwickelt wurde.
Die RSA-Verschlüsselung ist ein revolutionäres &amp;ldquo;Public-Key-Kryptographie&amp;rdquo;-System, das es ermöglicht, den Schlüssel zur Verschlüsselung (öffentlicher Schlüssel) der ganzen Welt zugänglich zu machen, während nur der Empfänger den Schlüssel zur Entschlüsselung (privater Schlüssel) kennt.&lt;/p>
&lt;p>Diese Asymmetrie beruht auf der rechnerischen Sicherheit der Tatsache, dass &amp;ldquo;es extrem schwierig ist, eine riesige zusammengesetzte Zahl in ihre Primfaktoren zu zerlegen&amp;rdquo;.&lt;/p>
&lt;h3 id="71-wie-die-rsa-verschlüsselung-funktioniert-schlüsselgenerierung-verschlüsselung-entschlüsselung">7.1 Wie die RSA-Verschlüsselung funktioniert (Schlüsselgenerierung, Verschlüsselung, Entschlüsselung)
&lt;/h3>&lt;p>Lassen Sie uns den gesamten Kommunikationsfluss der RSA-Verschlüsselung anhand eines Mermaid-Sequenzdiagramms untersuchen.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice["Alice (Empfänger)"]
participant Bob["Bob (Sender)"]
Alice->>Alice: "Generiere riesige Primzahlen p, q"
Alice->>Alice: "Berechne N = p * q, φ(N) = (p-1)(q-1)"
Alice->>Alice: "Berechne öffentlichen Schlüssel e und privaten Schlüssel d (e*d ≡ 1 mod φ(N))"
Alice->>Bob: "Sende öffentlichen Schlüssel (N, e)"
Note over Bob: "Bereite Klartext M vor (M &lt; N)"
Bob->>Bob: "Berechne Geheimtext C = M^e mod N"
Bob->>Alice: "Sende Geheimtext C"
Alice->>Alice: "Entschlüssele durch Berechnen des Klartextes M = C^d mod N"&lt;/div>
&lt;p>Im Folgenden erklären wir die mathematischen Schritte im Detail.&lt;/p>
&lt;h4 id="schritt-1-schlüsselgenerierung-arbeit-der-empfängerin-alice">Schritt 1: Schlüsselgenerierung (Arbeit der Empfängerin Alice)
&lt;/h4>&lt;ol>
&lt;li>Generiere zufällig zwei riesige Primzahlen $p$ und $q$ (hier wird der zuvor erwähnte Primzahltest verwendet).&lt;/li>
&lt;li>Berechne ihr Produkt $N = p \times q$. Dieses $N$ wird veröffentlicht.&lt;/li>
&lt;li>Berechne $\phi(N) = (p-1)(q-1)$ unter Verwendung der Eulerschen Phi-Funktion.&lt;/li>
&lt;li>Wähle eine ganze Zahl $e$ (öffentlicher Exponent), die teilerfremd zu $\phi(N)$ ist (oft wird $e = 65537$ verwendet).&lt;/li>
&lt;li>Berechne das modulare Inverse $d$ (privater Exponent) von $e$. Finde also $d$ so, dass Folgendes gilt:
$$ e \cdot d \equiv 1 \pmod{\phi(N)} $$
Für diese Berechnung wird der &lt;strong>erweiterte euklidische Algorithmus&lt;/strong> verwendet.&lt;/li>
&lt;/ol>
&lt;p>Der &lt;strong>öffentliche Schlüssel ist somit $(N, e)$&lt;/strong> und der &lt;strong>private Schlüssel ist $(N, d)$&lt;/strong>. ($p, q$ und $\phi(N)$ sollten sofort vernichtet oder streng geheim gehalten werden).&lt;/p>
&lt;h4 id="schritt-2-verschlüsselung-arbeit-des-senders-bob">Schritt 2: Verschlüsselung (Arbeit des Senders Bob)
&lt;/h4>&lt;p>Nehmen wir an, Bob möchte die Nachricht $M$ an Alice senden ($M$ ist eine numerische Darstellung von Zeichen, und $0 \le M &lt; N$).
Bob verwendet Alices öffentlichen Schlüssel $(N, e)$, um die folgende Berechnung durchzuführen und den Geheimtext $C$ zu erstellen:&lt;/p>
$$
C \equiv M^e \pmod N
$$
&lt;p>Dieser $C$ wird über das Netzwerk an Alice gesendet.&lt;/p>
&lt;h4 id="schritt-3-entschlüsselung-arbeit-der-empfängerin-alice">Schritt 3: Entschlüsselung (Arbeit der Empfängerin Alice)
&lt;/h4>&lt;p>Nach Erhalt des Geheimtextes $C$ führt Alice die folgende Berechnung unter Verwendung des privaten Schlüssels $d$ durch, den nur sie kennt:&lt;/p>
$$
M' \equiv C^d \pmod N
$$
&lt;p>Erstaunlicherweise stimmt das Ergebnis dieser Berechnung $M'$ perfekt mit der ursprünglichen Nachricht $M$ überein.&lt;/p>
&lt;h3 id="72-warum-kann-es-entschlüsselt-werden-mathematischer-beweis">7.2 Warum kann es entschlüsselt werden? (Mathematischer Beweis)
&lt;/h3>&lt;p>Hier zeigen der kleine Satz von Fermat (und der Satz von Euler) ihren wahren Wert. Warum kehrt $C^d \pmod N$ zu $M$ zurück?&lt;/p>
&lt;p>Lassen Sie uns die Entschlüsselungsformel erweitern.
Da $C \equiv M^e \pmod N$, haben wir:
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Im Schritt der Schlüsselgenerierung haben wir $d$ so gewählt, dass $e \cdot d \equiv 1 \pmod{\phi(N)}$. Das bedeutet, es gibt eine ganze Zahl $k$, sodass wir schreiben können:
&lt;/p>
$$ e \cdot d = 1 + k \cdot \phi(N) $$
&lt;p>Setzen wir dies in die obige Gleichung ein:
&lt;/p>
$$ M^{ed} = M^{1 + k \cdot \phi(N)} = M \cdot M^{k \cdot \phi(N)} = M \cdot (M^{\phi(N)})^k \pmod N $$
&lt;p>Hier kommt der &lt;strong>Satz von Euler&lt;/strong> ($M^{\phi(N)} \equiv 1 \pmod N$) ins Spiel. (&lt;em>Streng genommen müssen $M$ und $N$ teilerfremd sein, aber in RSA ist die Wahrscheinlichkeit, dass $M$ und $N$ nicht teilerfremd sind, astronomisch gering, und mithilfe des Chinesischen Restsatzes kann bewiesen werden, dass es auch gilt, wenn sie nicht teilerfremd sind&lt;/em>).&lt;/p>
&lt;p>Wenden wir den Satz von Euler an, da $M^{\phi(N)} \equiv 1$ ist:
&lt;/p>
$$ M \cdot (1)^k \equiv M \pmod N $$
&lt;p>Hervorragend, $M$ wurde wiederhergestellt! Die Eigenschaften von Zahlen, die von Fermat und Euler vor Hunderten von Jahren entdeckt wurden, garantieren perfekt die Vertraulichkeit der modernen digitalen Kommunikation.&lt;/p>
&lt;hr>
&lt;h2 id="8-spielzeug-implementierung-der-rsa-verschlüsselung-python">8. Spielzeug-Implementierung der RSA-Verschlüsselung (Python)
&lt;/h2>&lt;p>Da es schwer ist, ein Gefühl nur für die Theorie zu bekommen, verwenden wir Python, um den Prozess der RSA-Schlüsselgenerierung, Verschlüsselung und Entschlüsselung tatsächlich zu implementieren. Dies ist eine &amp;ldquo;Spielzeug-Implementierung&amp;rdquo; für Bildungszwecke, aber die verwendete Mathematik ist genau dieselbe wie bei der echten.&lt;/p>
&lt;p>Wir fügen auch den &amp;ldquo;erweiterten euklidischen Algorithmus&amp;rdquo; hinzu, um das modulare Inverse $d$ zu finden.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Größten gemeinsamen Teiler finden&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Erweiterter euklidischer Algorithmus (findet x, y für ax + by = gcd(a,b))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Verwendet, um d für e*d ≡ 1 (mod φ(N)) zu finden&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">Exception&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Inverses existiert nicht&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="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Primzahl-Generierungsfunktion (Vereinfachte Version: generiert kleine Primzahlen)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getrandbits&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Einfacher Test anstelle des zuvor erwähnten Fermat-Tests&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># RSA-Schlüsselgenerierung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Stellen Sie sicher, dass p und q nicht gleich sind&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Für e werden oft Primzahlen wie 65537 verwendet, aber hier wird es zufällig gewählt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Berechnung des privaten Schlüssels d&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Öffentlicher Schlüssel (e, n), Privater Schlüssel (d, n)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Berechne plaintext^e mod n&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cipher&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">cipher&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Berechne cipher^d mod n und konvertiere zurück in Zeichen&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">plain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">chr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plain&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ausführungsbeispiel&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;--- RSA-Verschlüsselung Spielzeug-Implementierung ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">private_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># Verwendet 12-Bit-Primzahlen&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, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Privater Schlüssel (d, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Hello Math!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Ursprüngliche Nachricht: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Verschlüsselung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">encrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Geheimtext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">encrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Entschlüsselung&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encrypted_msg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Entschlüsselte Nachricht: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Wenn Sie diesen Code ausführen, können Sie sehen, wie ein Array von Zeichen in ein Array unvertrauter Zahlen (Geheimtext) umgewandelt wird, welches durch den privaten Schlüssel wunderschön in den ursprünglichen String wiederhergestellt wird.&lt;/p>
&lt;hr>
&lt;h2 id="9-fazit-die-kreuzung-von-mathematischer-schönheit-und-praktikabilität">9. Fazit: Die Kreuzung von mathematischer Schönheit und Praktikabilität
&lt;/h2>&lt;p>Als Pierre de Fermat im 17. Jahrhundert diesen &amp;ldquo;kleinen Satz&amp;rdquo; entdeckte, dachte niemand, dass er für irgendetwas nützlich sein würde. Fermat selbst betrieb zahlentheoretische Forschung aus reiner mathematischer Neugier.&lt;/p>
&lt;p>Etwa 300 Jahre später, in den 1970er Jahren, an den Anfängen von Computernetzwerken, feierte der Satz von Fermat jedoch ein dramatisches Comeback als unverzichtbare Verschlüsselungstechnologie zur Etablierung sicherer Kommunikationsprotokolle. Die Primzahltesttechnologie, die auf dem kleinen Satz von Fermat basiert, und die RSA-Verschlüsselung, die auf dem Satz von Euler basiert, stützen buchstäblich die moderne Internet-Infrastruktur.&lt;/p>
&lt;p>Die LINE-Nachrichten, die wir jeden Tag beiläufig senden, und unsere Einkäufe bei Amazon tanzen alle auf dieser einfachen und schönen Formel $a^{p-1} \equiv 1 \pmod p$. Egal wie abstrakt Mathematik ist, der kleine Satz von Fermat lehrt uns, dass immer die Zeit kommen wird, in der sie für die Menschheit nützlich sein wird.&lt;/p>
&lt;p>Beim Erlernen von Programmierung und Kryptographietheorie wird das Verständnis der zugrunde liegenden mathematischen Strukturen eine starke Waffe sein, um das Verhalten von Bibliotheken, die als Blackboxes bereitgestellt werden, tiefgreifend zu verstehen und sicherere Systeme zu entwerfen.&lt;/p></description></item><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>【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></channel></rss>