Wer an einer mathematischen Erklärung des Verfahrens hinter der RSA Verschlüsselung (auch RSA Cryptosystem genannt) interessiert ist, oder auch wem die einfache Erklärung nicht ausreicht, der ist hier genau richtig. Ich beschreibe kurz und (hoffentlich) verständlich, wie man Nachrichten mit dem RSA Verfahren verschlüsselt.
Ich werde dabei so wenig Formalismus wie möglich und so viel wie nötig mit einbringen, da man es sich sonst auch bei Wikipedia anlesen kann. Man braucht für diese Seite ein Grundverständnis von Mathematik, also man sollte wissen was mit der Menge gemeint ist, was ist der größte gemeinsame Teiler ist, Grundverständnis von Äquivalenz-Umformungen, etc.
Aber es reicht aus, wenn man alles im Kapitel „Grundbegriffe der RSA Verschlüsselung“ verstanden hat.
Beispiele finden sich ganz unten, dabei habe ich mir ein kleines und ein größeres Beispiel ausgedacht (und nein, die sind nicht von Wikipedia kopiert, wie alle anderen Beispiele im Netz 😉 ).
Wer Nachrichten im realen Leben mittels RSA Verschlüsselung sichern möchte, der sollte sich Enigmail für Thunderbird angucken. Im verlinkten Artikel findet sich eine Schritt-für-Schritt-Beschreibung der Einrichtung von Enigmail.
Inhaltsverzeichnis
Grundbegriffe der RSA Verschlüsselung
… besser gesagt die Mathematischen Grundbegriffe dahinter.
Primzahl
Zunächst sollte klar sein was eine Primzahl ist: Eine Zahl größer als 1 (nicht größer gleich 1!) und die nur durch 1 und sich selbst Teilbar ist. 0 und 1 sind keine Primzahlen, die kleinste Primzahl ist 2!
Kongruenz und Modulo
Es sollte auch der Begriff der Kongruenz klar sein. Zwei Zahlen und sind gegenüber einer Zahl Kongruent, wenn sie den selben Divisionsrest haben.
Beispiel: 27 und 51 sind gegenüber 6 Kongruent, denn beide haben den Divisionsrest 3. Man schreibt es als . Das ist dabei die Modulo Funktion (in der Programmierung meistens als %
-Operator gebräuchlich) und gibt den Divisionsrest als Ergebnis aus. Der Teiler (hier die 6) wird auch als Modul bezeichnet, was später nochmal auftaucht.
Restklassen und Repräsentanten
Viel wichtiger sind Restklassen.
Eine Restklasse ist eine Menge an Zahlen, die alle den gleichen Divisionsrest bezüglich eines Modulo haben. Man schreibt dafür , wenn man sagt „Die Zahl ist in der Restklasse Modulo enthalten„.
Beispielsweise gilt für 3 und 27 mit Modulo 6: damit gilt .
Wörtlich: Die 27 ist in der Restklasse 3 Modulo 6 enthalten, also in der Menge, in der alle Zahlen drin sind, die den Divisionsrest 3 bezüglich der 6 haben. Das sind also alle Zahlen der Form mit (also 3 plus ein Vielfaches von 6) was wie Menge erzeugt.
Etwas formaler: Für alle in dieser Restklasse gilt . Es ist sehr wichtig, dass man Restklassen versteht, wenn man die Mathematik hinter der RSA Verschlüsselung verstehen möchte.
Das wird auch Repräsentant der Restklasse genannt. Allgemein ist jede Zahl und einer Restklasse genau dann ein Repräsentant dieser Restklasse, wenn gilt. Im obigen Beispiel sind also 0, 1, 2, 3, 4, 5 Repräsentanten, da alle kleiner als 6 sind. Für die 6 selbst würde wieder gelten und so würde man die 0 als Repräsentanten wählen.
Multiplikatives Inverses innerhalb einer Restklasse
Wo wir schon bei Restklassen sind, muss man auch wissen, was das multiplikative Inverse einer Zahl zu einem bestimmten Modulo ist (also einer Zahl innerhalb einer Restklasse). Für das multiplikative Inverse einer Zahl bezüglich gilt .
Man findet das multiplikative Inverse mittels des Euklid’schen Algorithmus für den ggt (größten gemeinsamen Teiler) gepaart mit einem Verfahren zum Rückeinsetzen. Dabei hilft die Tatsache, dass man schreiben kann, wobei gilt. Gut erklärt in diesem Skript unter Kapitel 2.2.4.
Mini-Exkurs zur Vorstellung was das multiplikative Inverse ist:
Wenn man nicht in einer Restklasse, sondern z.B. in den Natürlichen Zahlen rechnet, so ist das multiplikative Inverse gegenüber genau der Kehrwert , denn .
Eulersche phi-Funktion
Für später brauchen wir auch noch die Eulersche phi-Funktion, sie gibt die Anzahl der Teilerfremden Zahlen bis zu einer Grenze an. So ist beispielsweise ist (es gibt 16 Zahlen von 0 bis 39, die zu 40 teilerfremd sind), wohingegen bei 41 (also einer Primzahl) ist.
Generell gilt: Bei einer Primzahl ist (Begründung hier). Das ist für später sehr wichtig und hilfreich.
Gruppen (für interessierte)
Interessierte sollten auch die Struktur einer Gruppe kennen, denn auf ihr basiert das Verfahren der RSA Verschlüsselung (genauer gesagt basiert die Idee der Restklasse auf Ringen und die wiederum auf Gruppen). Ich werde darauf aber weniger eingehen, da das Feld der Gruppentheorie zu weit führt 😉
Im Prinzip ist eine Gruppe aber nichts anderes als eine Menge an Elementen mit einer Verknüpfung. Beispiel: (Menge an ganzen Zahlen) mit (Addition) bildet eine Gruppe. Darüber hinaus gelten verschiedene Axiome, die man aber nachlesen kann 😉
Schlüsselerzeugung
Für die RSA Verschlüsselung benötigen wir zunächst den öffentlichen und den privaten Schlüssel (da die RSA Verschlüsselung ein asymmetrisches Verfahren ist). Den groben Nutzen und die Verwendung dieser beiden Schlüssel habe ich ein der allgemeinen Erklärung beschrieben.
Schritt 1: Primzahlen finden
Zunächst wählt man zwei ungleiche Primzahlen. Je nach Bit-Länge der (üblich sind derzeit 1024 oder 2048 Bit) Zahlen sind diese mehrere hundert Dezimalstellen lang. Die beiden werden meistens und genannt und es muss eben gelten.
Schritt 2: RSA-Modul berechnen
Danach wird das RSA-Modul (zum Begriff Modul s.o.) berechnet. Wir nennen es und es wird mittels berechnet. Ver- und Entschlüsselte Nachrichten werden stets betrachtet.
Warum muss sein?
Um eine RSA Verschlüsselung zu knacken müsste man aus dem die Primfaktoren und finden, welche man für Ver- und Entschlüsselung benötigt. Wer das Wort Primfaktoren hört wird auch schnell an Primfaktorzerlegung denken und genau das müsste man machen. Um eine Nachricht entschlüsseln zu können müsste man in seine beiden Primfaktoren zerlegen, was durch die Größe von jedoch nicht in brauchbarer Zeit machbar ist.
Schritt 3: Die phi-Funktion und der Verschlüsselungsexponent
Danach kommt die erwähnte phi-Funktion. Wir benötigen wobei gilt, was sich leicht berechnen lässt: .
Wenn man den Wert von bestimmt hat, sucht man sich eine Zahl mit für die gilt, dass sie teilerfremd zu ist. Diese Zahl wird auch Verschlüsselungsexponent genannt, denn man braucht sie zum Verschlüsseln.
Warum muss gelten und warum müssen und teilerfremd sein?
Man sollte meinen, dass es mehr Sinn macht, wenn man statt direkt betrachtet, aber dem ist nicht so. Grund dafür ist der Satz von Euler-Fermat, der besagt, dass gilt. Dieser Satz ist sehr wichtig, da er der Grundstein für das erfolgreiche entschlüsseln ist. Warum diese Kongruenzbedingung bei den Schlüsselexponenten gelten muss wird beim entschlüsseln klar (weiter unten gibt es eine kleine Erklärung zu dem Satz von Euler-Fermat).
Schritt 4: Der Entschlüsselungsexponent
Nun kommt das multiplikative Inverse zum Einsatz, denn damit finden wir den Entschlüsselungsexponenten , er ist das multiplikative Inverse zum Verschlüsselungsexponenten bezüglich .
Es gibt verschiedene Verfahren das multiplikative Inverse zu finden, aber am einfachsten ist das Verfahren über den Euklid Algorithmus für den größten gemeinsamen Teiler (bereits oben beschrieben).
Die Schlüssel
Bisher haben wir nur die Schlüsselexponenten berechnet, doch der eigentliche öffentliche und private Schlüssel enthält zusätzlich noch den RSA-Modul, damit man beim ver-/entschlüsseln weiß in welche Restklasse man sich befindet.
Die eigentlichen Schlüssel sind Tupel aus dem Exponenten und dem RSA-Modul, sprich (öffentlichen Schlüssel) und (privaten Schlüssel).
Wer die Sachen mit Restklassen und multiplikativen Inversen verstanden hat, der weiß auch warum als privater und als öffentlicher Schlüssel (also öffentlichen und privaten Schlüssel vertauscht) genauso gut funktioniert und kein Sicherheitsrisiko für die RSA Verschlüsselung birgt.
Die Primzahlen und , sowie der Wert werden nun nicht mehr benötigt und können (bzw. sollten) gelöscht werden.
Ver- und Entschlüsseln einer Nachricht
Vorbereitung: Nachricht codieren
Zunächst muss man die zu verschlüsselnde Nachricht in eine Zahl codieren. Der ASCII, bzw. mittlerweile der UTF-Standard, hilft da ungemein. Man kann nun also eine Nachricht in eine Zahl umwandeln.
Formal muss jedoch für die Nachricht folgendes gelten: . Simpel, aber sonst geht durch die Modulo Funktion eine Menge Information verloren. Gilt diese Eigenschaft nicht mehr, so muss man die Nachricht aufteilen und mehrere Blöcke verschlüsseln.
Verschlüsseln
Nun geht es an das eigentliche verschlüsseln.
Wir haben also eine Nachricht , die als Zahl codiert wurde, mit und den öffentlichen Schlüssel .
Nun können wir verschlüsseln. Dabei rechnen wir einfach in der Restklasse Modulo , sprich die Restklasse . Man nimmt nun den Repräsentanten als verschlüsselte Nachricht und verschickt diesen.
Entschlüsseln
Das entschlüsseln geht denkbar einfach: Man rechnet innerhalb der Restklasse Modulo , also , und der Repräsentant dieser Restklasse ist dann die entschlüsselte Nachricht.
Das funktioniert, da und eben multiplikativ invers sind. Genauer gesagt wegen dem Satz von Euler-Fermat, der besagt, dass gilt.
Man kann das auch einfach herausfinden. Zunächst gibt es ein , sodass gilt. Da gilt findet man das auch tatsächlich. Außerdem gilt durch Potenzgesetze und man etwas umformen:
Hier noch eine Erklärung zum Schritt . Man kann den Beweis aufteilen in insgesamt drei Fälle, aber bei allen Fällen kommt es darauf hinaus, dass ist (was man auch noch beweisen kann, aber nun gut).
Den ausführlichen Beweis findet man hier in Kapitel 3.2.
Beispiele
Da in den beiden Beispielen sehr große Zwischenergebnisse vorkommen, kann man entweder zu Algebra-Software greifen oder online Angebote wie WolframAlpha nutzen. Für reale Szenarien mit RSA Verschlüsselung gibt es natürlich Verfahren wie man dennoch mit so großen Zahlen gut rechnen kann.
Kleines Beispiel
Wir möchten nun eine kleine Nachricht verschlüsslen. Sagen wir den Buchstaben C
, welcher den ASCII Code 67 hat. Gegeben ist also schon mal . Wir brauchen nun zwei Primzahlen, die groß genug sind. Sagen wir und . Dadurch ist und .
Hier noch mal die gegebenen Zahlen:
Schlüssel generieren
Wir brauchen zunächst die teilerfemde Zahl mit . Sagen wir . Der öffentliche Schlüssel ist also .
Das multiplikative Inverse von 175 Modulo 432 ist 79. Dadurch ist der private Schlüssel .
Verschlüsseln
Jetzt erhalten wir als Sender den öffentlichen Schlüssel und verschlüsseln damit unsere Nachricht.
Einfach rechnen, sprich . Die verschlüsselte Nachticht lautet also 115, was als ASCII Buchstabe ein s
wäre.
Entschlüsseln
Als Empfänger mit dem privaten Schlüssel können wir nun rechnen (wobei natürlich unsere 115 ist), also . Die Nachricht lautet also 67 und wenn wir uns an den Anfang dieses Beispiels erinnern stimmt das auch.
Großes Beispiel
Meistens möchte man aber größere Nachrichten als einen Buchstaben verschlüsslen. Da die Zahlen dann sehr sehr groß werden, wir aber hier im Beispiel nicht mit gigantischen Zahlen hantieren möchten, kann man die Nachricht in Blöcke unterteilen und dann verschlüsseln. Ich werde hier jeden Buchstaben als Block ansehen und die Rechenschritte etwas verkürzen.
Als Nachricht nehmen wir curi0sity
und als Schlüssel die aus dem kleinen Beispiel von oben. Also öffentlicher Schlüssel und privater Schlüssel . Die Nachricht codieren wir Buchstabenweise in Zahlen nach dem ASCII-Standard, sprich
Verschlüsseln
Als Sender rechnen wir für jeden Nachrichtenteil ganz normal .
Das 48 und 121 genau sich selbst als Ergebnis haben ist hier tatsächlich Zufall. Auch kann man bei Buchstabenweiser Verschlüsselung natürlich herausfinden welche Buchstaben an welchen Positionen vermutlich identisch sind. Man würde bei realer Verschlüsselung größere Blöcke nehmen.
Als ASCII String wäre aus curi0sity
der String ĽŬƐœ0Ćœöy
geworden. Meistens macht man jedoch eine Base64
-Codierung darauf woraus dann xL3FrMaQxZMwxIbFk8O2eQ==
wird. Das kann man dann leichter als E-Mail versenden.
Entschlüsseln
Als Empfänger der verschlüsselten Nachricht (ggf. convertiert man die Base64
-Codierung vorher zurück) rechnen wir einfach , was mit dem privaten Schlüssel wie folgt aussieht:
Damit hat man die originale Nachricht curi0sity
wieder zurück.