Suche

RSA: Der unknackbare Code?

Coverbild Illustration

Übersicht

Sekundarstufe

Mathematik, Informatik

Quantencomputing

Auf einen Blick

Schlüsselbegriffe: Verschlüsselung, Entschlüsselung, Modulo-Arithmetik, Klartext, Chiffretext, modulare Potenzen, Kryptographie
Alter: 16–18 Jahre
Vorkenntnisse/Fertigkeiten: Basiswissen in Python
Zeitumfang: 60 Minuten

Autor: Sam Robbins (UK)

Inhalt

Unterrichtsplan
Aufgaben und Hinweise für Lehrkräfte
Fermats kleiner Satz
  • Aufgabe 1
Hinweis zur Implementierung
  • Aufgabe 2
Der RSA-Algorithmus
Zusammenfassung des Prozesses (Tabelle)
  • Aufgabe 3
Der RSA-Algorithmus: Zusammenfassung
Das Brechen von RSA auf einem klassischen Computer
  • Aufgabe 4
Zusammenfassung

Zusammenfassung

Dies ist die erste von zwei Unterrichtsstunden mit dem Ziel zu zeigen, wie das RSA-Verschlüsselungsverfahren funktioniert und wie Quantencomputer dieses Verfahren künftig möglicherweise brechen könnten.

Diese Unterrichtsstunde konzentriert sich ausschließlich auf das RSA-System selbst, die Funktionsweise der Verschlüsselung und den klassischen Ansatz zum Knacken des Codes.

Illustration zu Quantum Algorithms

Unterrichtsplan
 

Zeit in MinutenUnterrichtsphaseAktivitätMaterial
0–5Aufgabe 1Einführung in Fermats kleinen SatzArbeitsblatt,
Taschenrechner
5–15Aufgabe 2Die Lehrkraft erklärt modulare Potenzen durch wiederholte Multiplikation innerhalb der Modulo-Arithmetik. Schüler*innen implementieren den Programmcode und testen ihn anhand der Beispiele.Arbeitsblatt,
Python Interpreter
15–20Einführung in das RSA-Verfahren am BeispielLehrkraft erklärt Verschlüsselung und Entschlüsselung in RSA an dem Beispiel auf dem AB.Arbeitsblatt
20–40Aufgabe 3Schüler*innen übernehmen den Code und testen die Ver- und Entschlüsselung in RSA an weiteren Beispielen.Arbeitsblatt,
Python Interpreter
40–60Aufgabe 4Schüler*innen entwerfen ein Programm zum Faktorisieren einer Zahl und messen die benötigte Zeit.Arbeitsblatt,
Python Interpreter

Aufgaben und Hinweise für Lehrkräfte

In dieser Lektion beschäftigen wir uns mit dem RSA-Verschlüsselungsalgorithmus und klassischen Methoden, ihn zu brechen. Der RSA-Algorithmus wurde 1979 von Rivest, Shamir und Adleman entwickelt und ist bis heute eine der erfolgreichsten Formen der Verschlüsselung. Wenn du jemals eine Finanztransaktion im Internet durchgeführt hast, ist es sehr wahrscheinlich, dass die dabei verwendeten Sicherheitscodes mithilfe des RSA-Systems verschlüsselt und deine Identität darüber verifiziert wurde.

Diese Lektion untersucht die Methodik des RSA-Verfahrens und zeigt, warum es in der klassischen Informatik praktisch unknackbar ist.

Arbeitsblatt

Die folgenden Aufgaben können Sie als Arbeitsblatt in pdf oder docx herunterladen.

Die Aufgaben finden Sie hier auch als interaktives Arbeitsblatt mit einer eingebetteten Python-Umgebung.

Fermats kleiner Satz

Im Zentrum des RSA-Verfahrens steht ein schönes mathematisches Resultat, bekannt als Fermats kleiner Satz:

x p1 1 ( mod p )

Das bedeutet: Wenn man eine natürliche Zahl x mit einer um eins verminderten Primzahl p (also mit p1) potenziert, dann ergibt der Rest bei Division durch p immer 1. Die mod-Funktion („modulo“) gibt den Rest nach der Division an.

Zum Beispiel nehmen wir x=3 und p=5:

3 p 1 = 3 4 = 81

81 / p = 81 / 5 = 16 Rest 1

Aufgabe 1

Überprüfe Fermats kleinen Satz für folgende Werte von x und p:

  1. x=2, p=3
  2. x=2, p=5
  3. x=4, p=5
  4. x=4, p=7
  5. x=5, p=11

Die Lehrkraft sollte zunächst demonstrieren, wie Modulo-Arithmetik funktioniert, z. B. Rest bei Division verschiedener Zahlen durch eine feste Zahl bestimmen.

Bei jeder Teilaufgabe ergibt sich 1.

Hinweis zur Implementierung

Das letzte Beispiel in Übung 1 zeigt ein potenzielles Problem bei der Implementierung von RSA: Die Potenzfunktion wächst extrem schnell. Selbst mit kleinen Primzahlen kann es schnell zu Überlauf-Fehlern kommen, wenn man die Potenz direkt berechnet. Das lässt sich vermeiden, indem man ausnutzt, dass eine Potenz denselben Rest besitzt, egal ob man als Basis die Zahl oder das Ergebnis verwendet. Man kann also Zwischenergebnisse bei jeder Multiplikation modulo p reduzieren.

Nehmen wir zum Beispiel wieder x=3 und p=5, sehen wir:

34 = 92

Aber:

9 4 ( mod 5 )

Statt 92 mit der Modulo-Operation zu berechnen, können wir 42 verwenden und finden wie gewünscht

42 = 16 1 ( mod 5 ).

Daher können wir zur Berechnung der modularen Potenz in Python eine Schleife schreiben, die x mehrfach mit sich selbst multipliziert und dabei jedes Mal den Rest modulo p berechnet.

Aufgabe 2

Implementiere den folgenden Python Code (% ist in Python die Notation für die Modulo-Operation):

def powerMod(a, b, c):  # raises a to the power of b modulo c
    res = a % c
    for i in range(0, b - 1):
        res = a * res % c
    return res

x = 5
p = 11

print(
    powerMod(x, p - 1, p)
)

Nutze den Code, um herauszufinden, welche der folgenden Zahlen keine Primzahlen sind (weil Fermats kleiner Satz für sie nicht gilt):

  1. 1367
  2. 1369
  3. 7527
  4. 7531
  5. 7537
  6. 15723
  7. 15727
  8. 18791

Die Lehrkraft demonstriert das Potenzieren durch wiederholte Multiplikation einer Zahl mit sich selbst. Dabei wird nach jedem Schritt das Ergebnis modulo gerechnet. Ein Beispiel ist im Arbeitsblatt enthalten.

Die Schüler*innen implementieren den Code vom Arbeitsblatt (% ist der Python-Befehl für MOD). Sie können jeden Wert von x kleiner als p ausprobieren (x=2 wäre hier ausreichend). Ergibt sich für einen Wert von x eine andere Ausgabe als 1, ist p keine Primzahl.

Antworten: (b), (c), (d), (f) und (h) sind keine Primzahlen.

Der RSA-Algorithmus

Hinweis

Der nächste Abschnitt erklärt die Mathematik hinter RSA Schritt für Schritt. Dieser Abschnitt kann übersprungen werden, falls der Fokus stärker auf dem Anwenden statt dem Begründen liegen soll.

Die Zusammenfassungstabelle am Ende dieses Abschnitts enthält alle notwendigen Informationen zur Implementierung des Systems.

RSA beruht auf einer Variante von Fermats kleinem Satz:

x ( p1 ) ( q1 ) 1 ( mod pq )

Als Beispiel nehmen wir x=2p=3 und q=5:

2 (p1) (q1) = 2 24 = 28 = 256

256 / (pq) = 256 / 15 = 17 Rest 1

Multipliziert man beide Seiten der Gleichung mit x, erhält man:

x (p1) (q1) x x (mod pq)

x (p1) (q1) +1 x (mod pq)

Dies bedeutet, dass man x (mod pq) erhält, wenn man x mit (p1)(q1)+1 potenziert. Der RSA Algorithmus nutzt diese Tatsache für eine Ver- und Entschlüsselung. Wenn wir zwei Zahlen e und d finden mit:

ed 1 ( mod (p1) (q1) ), dann gilt xed x (mod pq)

Ist x die zu verschlüsselnde Nachricht, definieren wir e als Verschlüsselungsschlüssel und d als Entschlüsselungsschlüssel. Die beiden Schlüssel zum Ver- und Entschlüsseln sind also unterschiedlich (dies nennt man auch asymmetrische Verschlüsselung).

Schritt 1 – Verschlüsselung

Wir potenzieren die Nachricht x mit e, um die verschlüsselte Nachricht y zu erhalten:

xe y (mod pq)

Die Sicherheit der RSA-Verfahrens beruht darauf, dass die Kenntnis von ye und pq nicht ausreicht, um x zu berechnen. Es gibt keinen eindeutigen Weg, um die e-te Wurzel in modularer Arithmetik zu berechnen. Dies kann man zum Beispiel durch Fermats kleinen Satz selbst sehen:

14 24 34 44 1 (mod 5)

Falls wir also die vierte Wurzel von 1 (mod 5) bestimmen wollen, können wir nicht wissen, ob die ursprüngliche Zahl 1, 2, 3 oder 4 ist.

Schritt 2 – Entschlüsselung

Um die verschlüsselte Nachricht y wieder zu entschlüsseln, wird diese Nachricht mit d (mod pq) potenziert. Mithilfe der Potenzgesetze erkennt man:

yd xe d xed x (mod pq)

Der RSA-Algorithmus: Zusammenfassung des Prozesses

 

SenderÖffentlichkeitEmpfänger
Was sie wissen
x (zu verschlüsselnde Nachricht)
e (Verschlüsselungsschlüssel)
pq (zu verwendendes Modul)

p oder q nicht einzeln bekannt
y (verschlüsselte Nachricht)
e (Verschlüsselungsschlüssel)
pq (zu verwendendes Modul)

p oder q nicht einzeln bekannt
y (verschlüsselte Nachricht)
d (Entschlüsselungsschlüssel)
pq (zu verwendendes Modul)

p und q sind einzeln bekannt, daher kann d errechnet werden
Was sie tun
Berechnen der verschlüsselten Nachricht
y = xe (mod pq)
Das Wissen über e und pq reicht nicht aus, um y zu entschlüsselnBerechnen der entschlüsselten Nachricht
x = yd (mod pq)

Beispiel

Wir verwenden p = 89, q = 151 und pq = 13439. Falls wir e = 7543 setzen, ist der zugehörige Entschlüsselungsschlüssel d = 7.

Wir verschlüsseln mit dem folgenden Python-Code die Beispielnachricht 8571:

def powerMod(a, b, c):  # raises a to the power of b modulo c
    res = a % c
    for i in range(0, b - 1):
        res = a * res % c
    return res

plainText = 8571
pq = 13439
e = 7543

encryptedMessage = powerMod(plainText, e, pq)
print(encryptedMessage)

Als verschlüsselte Nachricht sollte sich 1134 ergeben.

Im zweiten Schritt entschlüsseln wir diese Nachricht wieder mit dem Entschlüsselungsschlüssel d=7:

def powerMod(a, b, c):  # raises a to the power of b modulo c
    res = a % c
    for i in range(0, b - 1):
        res = a * res % c
    return res

cipherText = 1134
pq = 13439
d = 7

decryptedMessage = powerMod(cipherText, d, pq)
print(decryptedMessage)

Es ergibt sich wieder die ursprüngliche Nachricht 8571.

Das folgende Beispiel kann zur Überprüfung des RSA-Verfahrens verwendet werden:

7 7543 = 52801 und (p1) (q1) = 88 150 = 13200 , d. h.

ed 1 ( mod (p1) (q1) ) wie gefordert.

Ein passender Entschlüsselungsfaktor d mit ed 1 ( mod (p1) (q1) ) kann berechnet werden, wenn e und (p1) (q1) teilerfremd sind (die Berechnung erfolgt durch den Erweiterten Euklidischen Algorithmus, worauf in dieser Stunde aus Zeitgründen verzichtet wurde).

Eine mögliche Schülerfrage ist, warum ein Angreifer d nicht berechnen und damit den Code knacken kann. Die Antwort ist, dass man trotz Kenntnis von pq nicht von p und q einzeln kennt und damit auch nicht

(p1) (q1) .

Die Primfaktorzerlegung von pq ist sehr aufwändig, worin die Sicherheit des RSA-Verfahrens liegt.

SuS sollten zuerst das Beispiel implementieren und danach mit Aufgabe 3 weitermachen.

``

Aufgabe 3

Hinweis

Die Umwandlung von Zeichen in Zahlen kann mit ord() automatisiert werden. Diese Funktion liefert den ASCII-Code eines Zeichens. Die Umkehrfunktion chr() wandelt eine Zahl zurück in ein Zeichen. Je nach Python-Erfahrung können SuS automatische Umsetzung verwenden oder die Zeichen manuell in Zahlen umwandeln.

Die Beispielprogramme verwenden außerdem Reihungen und Schleifen zur Automatisierung der Verschlüsselung kompletter Nachrichten. Dies ist optional und abhängig vom Kenntnisstand der Lernenden.

Aufgabe 3a

Verwende pq=13439 und e = 5077, um die Nachricht QUANTUM zu verschlüsseln. Wandle jeden Buchstaben in eine Zahl um (A = 1, B = 2, …) und verschlüssele jeden Buchstaben einzeln.

Antworten: [4114, 5656, 1, 7072, 249, 5656, 12523]

Beispielcode:

def powerMod(a, b, c):  # raises a to the power of b modulo c
    res = a % c
    for i in range(0, b - 1):
        res = a * res % c
    return res

plainText = [
    "Q", "U", "A",
    "N", "T", "U",
    "M"
]

plainTextNumeric = []
for i in plainText:
    plainTextNumeric.append(ord(i) - 64)

pq = 13439
e = 5077

cipherTextNumeric = []
for i in plainTextNumeric:
    cipherTextNumeric.append(powerMod(i, e, pq))

print(cipherTextNumeric)

Aufgabe 3b

Entschlüssele die Nachricht wieder mit pq=13439 und d = 13.

Beispielcode:

def powerMod(a, b, c):  # raises a to the power of b modulo c
    res = a % c
    for i in range(0, b - 1):
        res = a * res % c
    return res

cipherTextNumeric = [
    4114, 5656, 1,
    7072, 249,
    5656, 12523
]

pq = 13439
d = 13

plainTextNumeric = []
for i in cipherTextNumeric:
    plainTextNumeric.append(powerMod(i, d, pq))

print(plainTextNumeric)

plainText = []
for i in plainTextNumeric:
    plainText.append(chr(i + 64))

print(plainText)

Der RSA-Algorithmus: Zusammenfassung

Das RSA-Verfahren besitzt zwei Schlüssel: einen öffentlichen Schlüssel und einen privaten (geheimen) Schlüssel. Der öffentliche Schlüssel besteht aus e und pq; der private Schlüssel besteht aus d und den einzelnen Zahlen p und q.

Der öffentliche Schlüssel kann ohne Einschränkungen herausgegeben werden, da dieser nur zum Verschlüsseln, aber nicht zum Entschlüsseln verwendet werden kann. Möchte eine Bank zum Beispiel eine geheim zuhaltende Transaktion mit einem Kunden (z. B. eine PIN oder eine Kartenprüfnummer einer Kreditkarte) durchführen, kann die Bank den öffentlichen Schlüssel veröffentlichen. Der Kunde kann seine Information über die Operation

xe y ( mod pq )

verschlüsseln und y an die Bank übermitteln. Selbst wenn ein Hacker die Nachricht abfängt und ebenfalls im Besitz des öffentlichen Schlüssels der Bank ist, kann dieser nicht die ursprüngliche Nachricht x berechnen. Nur die Bank selber kann mit dem privaten Schlüssel d die Nachricht entschlüsseln, um die geheime Information x zu lesen.

Das Brechen von RSA auf einem klassischen Computer

Um RSA zu brechen, muss man d kennen. Dazu benötigt man jedoch

(p1) (q1) .

Obwohl pq öffentlich ist, ist das Produkt

(p1) (q1)

nicht einfach zu bestimmen. Dazu müsste man pq in seine Primfaktoren zerlegen. Das ist für große Primzahlen p und q extrem aufwendig. Die folgende Aufgabe macht diese Herausforderung deutlich:

Aufgabe 4

Schreibe ein Programm, um die Zahl 900 239 055 271 631 zu faktorisieren. Stoppe die Zeit, die dein Programm benötigt, um die Faktoren p und q zu finden.

Je nach Python-Erfahrung benötigen Schülerinnen und Schüler eventuell Hinweise, beispielsweise:

  1. Schleife über alle Zahlen bis zur Quadratwurzel der Zielzahl erstellen.
  2. Zielzahl durch Schleifenvariable teilen. Falls sich eine ganze Zahl ergibt, ist ein Faktor gefunden.
  3. Um zu überprüfen, ob eine Zahl eine ganze Zahl ist, kann die Division x/i mit der Ganzzahldivision x//i verglichen werden (alternativ kann der Modulo-Befehl verwendet werden.)
  4. Bei positivem Ausgang des Tests Schleife beenden und Ergebnis ausgeben.

Antwort: 900,239,055,271,631 = 30,003,209 x 30,004,759

Beispielcode:

import time
import math

timeNow = time.time()
x = 900239055271631
i = 2
foundFactors = False

while foundFactors == False
and i < math.sqrt(x):
    i += 1
    if x / i == x // i:
        foundFactors = True

if foundFactors == True:
    print(i)
    print(int(x / i))

print(
    "Time taken = " +
    str(
        int(time.time() - timeNow)
    ) +
    " seconds"
)

Das Beispielprogramm nutzt die Systemzeitmessung zur Laufzeitanalyse (das ist optional). Die Aufgabe zeigt, dass selbst für vergleichsweise kleine Zahlen die Faktorisierung lange dauert. Auf dem verwendeten Rechner waren dies 25 Sekunden!

Zusammenfassung

Faktorisieren ist ein Beispiel für ein nur schwierig lösbares Problem: Es gibt eine Methode zum Finden der beiden Faktoren (Trial and Error Division), aber die benötigte Zeit wächst exponentiell mit der Größe der Zahl. Wählt man die beiden Primzahlen groß genug, könnten selbst Supercomputer das Produkt dieser Zahlen nicht in realistischer Zeit faktorisieren. In unserem Beispiel waren die beiden Primzahlen 8-stellig. In heutigen Implementationen von RSA werden typischerweise Primzahlen mit etwa je 300 Stellen verwendet. Damit ist derzeit RSA der Goldstandard der Internetsicherheit für abhörsichere Kommunikation.

Doch Quantencomputing könnte dieses Prinzip bedrohen: Mit Shors Algorithmus ließe sich die Komplexität der Faktorisierung reduzieren – so weit, dass RSA in Echtzeit gebrochen werden könnte. In der nächsten Lektion wirst du lernen, wie der Shor-Algorithmus die Sicherheit von RSA bedrohen kann und warum dies eine Revolution in der Kryptographie auslösen könnte.

Close search