Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Das RSA-Verfahren Klaus Becker 2017.

Ähnliche Präsentationen


Präsentation zum Thema: "Das RSA-Verfahren Klaus Becker 2017."—  Präsentation transkript:

1 Das RSA-Verfahren Klaus Becker 2017

2 Das RSA-Verfahren 2 An: Von: Hallo Bob!

3 Experimente mit CrypTool
Teil 1 3 Experimente mit CrypTool

4 Experimente mit CrypTool
4 Einen ersten Eindruck vom RSA-Verfahren kann man sich mit dem Software-Werkzeug CrypTool verschaffen. Dieses Werkzeug macht die wichtigsten Schritte des RSA-Verfahrens transparent. Experimente mit CrypTool lassen direkt erkennen, dass das RSA-Verfahren auf Berechnungen mit Zahlen beruht. Die Experimente führen aber noch nicht dazu, dass man versteht, warum gerade dieses Verfahren heutzutage benutzt wird. Hierzu sind vertiefende Untersuchungen erforderlich.

5 Experimente mit CrypTool
5 Mit den Menüpunkten [Einzelverfahren][RSA- Kryptosystem][RSA-Demo...] kommst du in Bereich, in dem das RSA- Verfahren durchgespielt werden kann. Gib zunächst zwei verschiedene Primzahlen in die dafür vorgesehenen Felder ein. Mit [Parameter aktualisieren] werden dann die beiden Schlüssel erzeugt.

6 Experimente mit CrypTool
6 Wähle jetzt [Optionen für Alphabet und Zahlensystem...] und lege die vom Programm vorgesehenen Optionen fest. Am besten übernimmst du zunächst die Einstellungen in der Abbildung (beachte das Leerzeichen im Alphabet).

7 Experimente mit CrypTool
7 Jetzt kannst du Texte (mit Zeichen aus dem voreingestellten Alphabet) verschlüsseln und die Verschlüsselung auch wieder entschlüsseln.

8 Vorbemerkung 8 Das RSA-Verfahren basiert auf modularem Rechnen. Um die Details des RSA-Verfahrens zu verstehen, muss man modulares Rechnen verstehen und einige zahlentheoretische Zusammenhänge kennen. Im Unterricht kann man die mathematischen Grundlagen vorab erarbeiten, oder – wie hier – bei der Entwicklung des RSA-Verfahres je nach Bedarf bereitstellen.

9 Verschlüsselung mit modularer Addition
Teil 2 9 Verschlüsselung mit modularer Addition

10 Vorbemerkung 10 Als Vorstufe zum RSA-Verfahren betrachten wir hier ein Verfahren, das auf modularer Addition beruht und bereits viele Ähnlichkeiten zum RSA-Verfahren aufweist. Der Vorteil dieser Vorgehensweise besteht darin, dass wir an das sehr einfache Caesar- Verfahren anknüpfen können und durch Verallgemeinerung schrittweise zu den zahlenbasierten Verfahren gelangen können.

11 Den Anfang macht Caesar
11 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z D E F G H I J K L M N O P Q R S T U V W X Y Z A B C Schlüssel: D Quelltext: Geheimtext: SALVEASTERIX VDOYHDVWHULA

12 Caesar-Verfahren mit Zahlen
12 Codierung: Umwandlung von Zeichen in Zahlen A → 00 B → Z → 25 A,S,T,E,R,I,X 00,18,19,04,17,08,23 Verschlüsselung: Verarbeitung von Zahlen (00 + 3) % 26 = 03 (18 + 3) % 26 = (23 + 3) % 26 = 00 00,18,19,04,17,08,23 03,21,22,07,20,11,00 Entschlüsselung: Verarbeitung von Zahlen ( ) % 26 = 00 ( ) % 26 = ( ) % 26 = 23 03,21,22,07,20,11,00 00,18,19,04,17,08,23 Decodierung: Umwandlung von Zahlen in Zeichen A → 00 B → Z → 25 00,18,19,04,17,08,23 A,S,T,E,R,I,X

13 Caesar-Variation: zusätzliche Zeichen
13 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 N,A,C,H, ,R,O,M 14,01,03,08,00,18,15,13 Verschlüsselung: Verarbeitung von Zahlen (14 + 9) % 27 = 23 (01 + 9) % 27 = (13 + 9) % 27 = 22 14,01,03,08,00,18,15,13 23,10,12,17,09,00,24,22 Entschlüsselung: Verarbeitung von Zahlen ( ) % 27 = 14 ( ) % 27 = ( ) % 27 = 13 23,10,12,17,09,00,24,22 14,01,03,08,00,18,15,13 Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26 14,01,03,08,00,18,15,13 N,A,C,H, ,R,O,M

14 Caesar-Variation: verallgemeinerte Addition
14 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 D,A, ,I,S,T, ,E,S 04,01,00,09,19,20,00,05,19 Verschlüsselung: Verarbeitung von Zahlen (e, n) = (18, 30) ( ) % 30 = 22 ( ) % 30 = ( ) % 30 = 07 04,01,00,09,19,20,00,05,19 22,19,18,27,07,08,18,23,07 Entschlüsselung: Verarbeitung von Zahlen (d, n) = (12, 30) ( ) % 30 = 04 ( ) % 30 = ( ) % 30 = 19 22,19,18,27,07,08,18,23,07 04,01,00,09,19,20,00,05,19 Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26 04,01,00,09,19,20,00,05,19 D,A, ,I,S,T, ,E,S

15 Caesar-Variation: Zeichenblöcke
15 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 HAL,LO 080112, Verschlüsselung: Verarbeitung von Zahlen (e, n) = (112233, ) ( ) % = ( ) % = 080112, 192345, Entschlüsselung: Verarbeitung von Zahlen (d, n) = (209088, ) ( ) % = ( ) % = 192345, 080112, Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26 080112, HAL,LO

16 Verfahren mit modularer Addition
16 (e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Schritt 1: Wahl der Blocklänge und Zerlegung des Textes Die Blocklänge legt die Länge der Texteinheiten fest, die mit Zahlen codiert werden und anschließend verschlüsselt werden. Je größer die Blocklänge, desto mehr Zahlen benötigt man zur Codierung der Texteinheiten. Bei einer Blocklänge 3 wird beispielweise der Text 'CAESAR' wie folgt in Texteinheiten zerlegt: 'CAE','SAR' Bei einer Zerlegung eines Textes kann es vorkommen, dass eine Texteinheit übrig bleibt, die nicht mehr die gesamte Blocklänge hat. In diesem Fall füllen wir den Text mit zusätzlichen Zeichen (hier Leerzeichen) auf: 'HAL','LO '

17 Verfahren mit modularer Addition
17 (e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Schritt 2: Wahl der Codierung Die Codierung ordnet jeder Texteinheit eine natürliche Zahl zu. Die Zuordnung muss eindeutig sein, so dass eine Decodierung möglich ist. Codierung von Zeichenblöcken: ' ' -> 0000 ' A' -> 0001 ' B' -> 0002 ... ' Z' -> 0026 'A ' -> 0100 'AA' -> 0101 'ZZ' -> 2626 Codierung von Zeichenblöcken: ' ' -> 000 ' A' -> 001 ' B' -> 002 ... ' Z' -> 026 'A ' -> 027 'AA' -> 028 'ZZ' -> 728 Codierung des Alphabets: ' ' -> 00 'A' -> 01 ... 'Z' -> 26

18 Verfahren mit modularer Addition
18 (e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Schritt 3: Wahl des Moduls und der Verschiebezahl Die Modulzahl n ist eine beliebige natürliche Zahl. Sie muss nur so gewählt werden, dass sie größer als die größtmögliche Codezahl einer Texteinheit ist. Die zu wählende Größe hängt demnach von der Blocklänge und der gewählten Codierung ab. Die Verschiebezahl e zum Verschlüsseln (e-ncrypt) ist eine beliebige natürliche Zahl, die kleiner als die Modulzahl n ist. Beide zusammen - Verschiebezahl und Modul - werden zur Verschlüsselung benötigt. Das Zahlenpaar (e, n) bildet den Schlüssel zur Verschlüsselung eines Textes. Dieser Schlüssel wird auch öffentlicher Schlüssel genannt. Schritt 4: Bestimmung des Gegenschlüssels Die Verschiebezahl d zum Entschlüsseln (d-ecrypt) ergibt sich direkt aus e und n: Es muss e+d=m gelten. Also ist d = n - e. Das Zahlenpaar (d, n) bildet den Schlüssel zur Entschlüsselung eines Textes. Dieser Schlüssel wird auch privater Schlüssel genannt.

19 Verfahren mit modularer Addition
19 (e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Schritt 5: Verschlüsselung codierter Texte Zur Verschlüsselung eine Codezahl x benötigt man den öffentlichen Schlüssel (e, m). Die Verschlüsselung erfolgt hier durch modulare Addition: x -> [x + e]%n Schritt 6: Entschlüsselung codierter Texte Zur Entschlüsselung eine Codezahl y benötigt man den privaten Schlüssel (d, n). Die Entschlüsselung erfolgt analog zur Verschlüsselung: y -> [y + d]%n

20 Übung 20 Benutze unsere Standardcodierung mit Blocklänge 2.
Erzeuge zunächst einen öffentlichen Schlüssel (wie z.B. (567, 2911)) und gib ihn deinem Nachbarn. Dein Nachbar soll jetzt mit diesem Schlüssel eine selbst gewählte (nicht zu lange) Nachricht mit dem oben beschriebenen Verfahren mit modularer Addition verschlüsseln und sie an dich weitergeben. Entschlüssele diese Nachricht.

21 Durchführung mit Python
21 Aufgabe: Eine Implementierung nutzen Lade die Datei chiffriersystemModularesAddieren.py (siehe inf-schule) herunter. Diese Datei enthält eine ganze Reihe von Funktionen, die Teilaufgaben beim Verfahren mit modularer Addition übernehmen. Mit den Funktionen kannst du jetzt interaktiv das Verfahren mit modularer Addition durchspielen. Führe selbst weitere Tests durch. >>> abc = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ' >>> block = 2 >>> oeffentlicherSchluessel = (2102, 3000) >>> privaterSchluessel = (898, 3000) >>> quelltext = 'ASTERIX' >>> quellcode = codierung(quelltext, block, abc) >>> quellcode [119, 2005, 1809, 2400] >>> geheimcode = verschluesselung(quellcode, oeffentlicherSchluessel) >>> geheimcode [2221, 1107, 911, 1502] >>> entschluesseltercode = verschluesselung(geheimcode, privaterSchluessel) >>> entschluesseltercode >>> entschluesseltertext = decodierung(entschluesseltercode, block, abc) >>> entschluesseltertext 'ASTERIX'

22 Durchführung mit Python
22 Aufgabe : Eine Implementierung nutzen Alternativ kann man auch ein kleines Testprogramm wie das folgende erstellen: from chiffriersystemModulareAddition import * # Vorgaben abc = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ' block = 2 oeffentlicherSchluessel = (2102, 3000) privaterSchluessel = (898, 3000) # Verarbeitung quelltext = 'COSINUS' quellcode = codierung(quelltext, block, abc) geheimcode = verschluesselung(quellcode, oeffentlicherSchluessel) entschluesseltercode = verschluesselung(geheimcode, privaterSchluessel) entschluesseltertext = decodierung(entschluesseltercode, block, abc) # Ausgaben print('Quelltext:') print(quelltext) print('Quellcode:') print(quellcode) print('Geheimcode:') print(geheimcode) print('entschlüsselter Code:') print(entschluesseltercode) print('entschlüsselter Text:') print(entschluesseltertext)

23 Korrektheit 23 Korrektheit:
(e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Korrektheit: Die Entschlüsselung macht die Verschlüsselung rückgängig: x → [x + e]%n → [[x + e]%n + d]%n = [x + [e + d]%n]%n = [x+n]%n = x […+d]%n x […+e]%n

24 Sicherheit 24 Sicherheit:
(e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit e+d=n. Sicherheit: Das additive Chiffrierverfahren ist nicht sicher, da man aus dem öffentlichen Schlüssel sofort den privaten Schlüssel bestimmen kann.

25 Exkurs - Modulares Rechnen
Teil 3 25 Exkurs - Modulares Rechnen

26 Uhrenaddition 26 Modulare Addition kennt man aus dem täglichen Leben.
Aufgabe: Ergänze die in der Tabelle fehlenden Angaben zur Uhrzeit (in MOZ / Moskauer Zeit). Wie rechnet man mit Uhrzeiten? Wie kann man z.B. direkt aus 17 und 149 zum Ergebnis 22 gelangen?

27 Modulare Gleichheit 27 Verallgemeinerte Uhrzeiten
Bei Beginn der Reise in Moskau ist es 17 Uhr. Nach 149 Stunden wird das Ziel Wladiwostok erreicht. Es ist jetzt (17+149) Uhr bzw. 166 Uhr. Das entspricht - auch im fernen Sibirien Uhr. Man kann diese Uhrzeit leicht rechnerisch ermitteln indem man den Rest bei der Division durch 24 ermittelt: 166 % 24 = 22 Uhrzeiten werden eigentlich nur mit den Zahlen 0, 1, ..., 23 angegeben. Im Alltag lässt man auch manchmal die Zahl 24 zu. 24 Uhr ist dasselbe wie 0 Uhr. Die 24 ist - bei Uhrzeitangaben - also gleich zu behandeln wie die 0. 31 Uhr und 55 Uhr (als verallgemeinerte Uhrzeiten) würden für dieselben Uhrzeiten stehen, weil der zyklisch sich drehende und immer wieder bei 0 neu beginnende Uhrzeiger dieselbe Stelle anzeigen würde. Rechnerisch zeigt sich das, indem beide Zahlen 31 und 55 denselben Rest bei der Division durch 24 hinterlassen. Def.: Vorgegeben sei eine natürliche Zahl n. Zwei natürliche Zahlen a und b heißen gleich modulo n bzw. kongruent modulo n genau dann, wenn sie beide den gleichen Rest bei der Division durch n erzeugen. Beispiel: 31 und 55 sind gleich modulo 24, denn es gilt: [31]%24 = 7 = [55]%24

28 Modulare Addition 28 Aufgabe:
(a) Führe die Rechnung für weitere Städte durch. (b) Darf man für EKATERINBURG auch so rechen: [ ]%24 = [17]%24 + [26]%24 = ... (c) Geht das auch für NOVOSIBIRSK? Was müsste man hier noch tun? [ ]%24 = [17]%24 + [46]%24 = ...

29 Modulare Addition 29 Vorgegeben sei eine natürliche Zahl n. Zwei natürliche Zahlen a und b werden modulo n addiert, indem man sie addiert und anschließend von der Summe den Rest bei der Division durch n berechnet. Das Ergebnis ist also [a+b]%n. Beachte, dass das Ergebnis bei der Addition modulo n immer eine Zahl kleiner als n ist. Aufgabe: Erstelle selbst eine Verknüpfungstafel für die Addition modulo n = 5. Rechengesetz (Modulare Gleichheit bei der Addition): Aus [a1]%n = [b1]%n und [a2]%n = [b2]%n folgt [a1+a2]%n = [b1+b2]%n. Das erste Rechengesetz besagt, dass Zahlen, die modulo n gleich sind, auch zu gleichen Additionsergebnissen modulo n führen. Rechengesetz (Addition und iterierte Modulberechnung): [a+b]%n = [[a]%n + [b]%n]%n Das zweite Rechengesetz erlaubt es, bei der Addition modulo n zuerst die Summanden zu verkleinern und dann erst die Addition durchzuführen.

30 Modulare Multiplikation
30 Vorgegeben sei eine natürliche Zahl n. Zwei natürliche Zahlen a und b werden modulo n multipliziert, indem man sie multipliziert und anschließend vom Produkt den Rest bei der Division durch n berechnet. Das Ergebnis ist also [a*b]%n. Beachte, dass das Ergebnis bei der Multiplikation modulo n immer eine Zahl kleiner als n ist. Aufgabe: Erstelle selbst eine Verknüpfungstafel für die Multiplikation modulo n = 8. Rechengesetz (Modulare Gleichheit bei der Multiplikation): Aus [a1]%n = [b1]%n und [a2]%n = [b2]%n folgt [a1*a2]%n = [b1*b2]%n. Das erste Rechengesetz besagt, dass Zahlen, die modulo n gleich sind, auch zu gleichen Multiplikationsergebnissen modulo n führen. Rechengesetz (Multiplikation und iterierte Modulberechnung): [a*b]%n = [[a]%n * [b]%n]%n Das zweite Rechengesetz erlaubt es, bei der Multiplikation modulo n zuerst die Faktoren zu verkleinern und dann erst die Multiplikation durchzuführen.

31 Modulare Potenz 31 Vorgegeben sei eine natürliche Zahl n. Eine natürliche Zahl a wird mit einer natürlichen Zahl x modulo n potenziert, indem man sie mit x potenziert und anschließend von der Potenz den Rest bei der Division durch n berechnet. Das Ergebnis ist also [ax]%n. Beachte, dass das Ergebnis bei der Potenzbildung modulo n immer eine Zahl kleiner als n ist. Aufgabe: (a) Berechne [34]%5. (b) Berechne [64]%5. Berechne auch [([([([6]%5)*6]%5)*6]%5)*6]%5. Was stellst du fest? (c) Welche Vorteile ergeben sich bei großen Zahlen, wenn man [ax]%n wie folgt berechnet: [(...([([a]%n)*a]%n)...)*a]%n ? Rechengesetz (Modulare Gleichheit bei der Potenzbildung): Aus [a]%n = [b]%n folgt [ak]%n = [bk]%n. Das erste Rechengesetz besagt, dass Zahlen, die modulo n gleich sind, auch zu gleichen Potenzierungsergebnissen modulo n führen. Rechengesetz (Potenzbildung und iterierte Potenzbildung): [ak]%n = [[a%n]k]%n = [(...([([a]%n)*a]%n)...)*a]%n Das zweite Rechengesetz erlaubt es, bei der Potenzbildung modulo n zuerst die Basis zu verkleinern und dann erst die Multiplikation durchzuführen.

32 Aufgaben 32 Bestätige die Rechengesetze für modulare Addition und Multiplikation anhand von Beispielen. Du kannst Python als Taschenrechner benutzen. >>> n = 14 >>> a1 = 16 >>> b1 = 19 >>> a2 = 44 >>> b2 = 75 >>> a1%n 2 >>> a2%n >>> b1%n 5 >>> b2%n >>> (a1+b1)%n ...

33 Verschlüsselung mit modularer Multiplikation
Teil 4 33 Verschlüsselung mit modularer Multiplikation

34 Vorbemerkung 34 Statt modularer Addition verwenden wir jetzt modulare Multiplikation als Grundlage eines Verschlüsselungsverfahres. Dieses Verfahen kann ebenfalls als Vorstufe zum RSA-Verfahren angesehen werden. Wir werden hier sehen, wie die Sicherheit eines Verfahrens davon abhängt, ob man über schnelle Algorithmen für bestimmte Problemstellungen verfügt.

35 Multiplikation statt Addition
35 (e, n) f(x, (e,n)) = [x+e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y+d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) (e, n) f(x, (e,n)) = [x*e]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [y*d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob)

36 Statt Addition ... Codierung: Umwandlung von Zeichen in Zahlen
36 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 N,I,X, ,L,O,S 14,09,24,00,12,15,19 Verschlüsselung: Verarbeitung von Zahlen (e, n) = (7, 30) (14 + 7) % 30 = 21 (09 + 7) % 30 = (19 + 7) % 30 = 26 14,09,24,00,12,15,19 21,16,01,07,19,22,26 Entschlüsselung: Verarbeitung von Zahlen (d, n) = (23, 30) ( ) % 30 = 14 ( ) % 30 = ( ) % 30 = 19 21,16,01,07,19,22,26 14,09,24,00,12,15,19 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 14,09,24,00,12,15,19 N,I,X, ,L,O,S

37 ... benutze Multiplikation!
37 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 N,I,X, ,L,O,S 14,09,24,00,12,15,19 Verschlüsselung: Verarbeitung von Zahlen (e, n) = (7, 30) (14 * 7) % 30 = 08 (09 * 7) % 30 = (19 * 7) % 30 = 13 14,09,24,00,12,15,19 08,03,18,00,24,15,13 Entschlüsselung: Verarbeitung von Zahlen (d, n) = (…, 30) (08 * d) % 30 = 14 (03 * d) % 30 = (13 * d) % 30 = 19 08,03,18,00,24,15,13 14,09,24,00,12,15,19 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 14,09,24,00,12,15,19 N,I,X, ,L,O,S

38 ... benutze Multiplikation!
38 Aufgabe: (a) Ermittle (durch Ausprobieren) die Zahl d, mit der man die Entschlüsselung hier völlig analog zur Verschlüsselung durchführen kann. (b) Welcher Zusammenhang besteht zwischen der Zahl e zum Verschlüsseln (hier 7), der Zahl d (hier ...) zum Entschlüsseln und der Modulzahl n (hier 30)? Verschlüsselung: Verarbeitung von Zahlen (d, n) = (…, 30) (08 * d) % 30 = 14 (03 * d) % 30 = (13 * d) % 30 = 19 08,03,18,00,24,15,13 14,09,24,00,12,15,19 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 14,09,24,00,12,15,19 N,I,X, ,L,O,S

39 Modulares Inverses 39 Def.: Zwei natürliche Zahlen a und b heißen modular invers zueinander bezüglich n genau dann, wenn gilt: [a*b]%n = 1. Beispiel: [2*3]%5 = 1. Die beiden Zahlen 2 und 3 sind also modular invers zueinander bzgl. 5. Die Zahl 2 ist das modulare Inverse von 3 bzgl. des Moduls 5. Ebenso ist 3 das modulare Inverse von 2 bzgl. des Moduls 5. Beispiel: [7*13]%30 = 1 Aufgabe: (a) Betrachte den Fall n = 5. Bestimme zu a = 1, 2, 3, 4 jeweils das modulare Inverse bzgl. n. (b) Betrachte den Fall n = 8. Bestimme zu a = 1, …, 7 jeweils das modulare Inverse bzgl. n. Klappt das immer? Für welche Zahlen gibt es ein modulares Inverses? (c) Betrachte den Fall n = 15. Hast du bereits eine Vermutung, für welche der Zahlen a = 1, 2, ..., 14 man das modulare Inverse bzgl. n bestimmen kann? Bestimme diese Inversen.

40 Existenz des modularen Inversen
40 Satz (über die Existenz des modularen Inversen): Gegeben sei eine natürliche Zahl n. Das modulare Inverse zu einer Zahl a ungleich Null existiert genau dann, wenn a und n keinen gemeinsamen Teiler größer als 1 haben - d.h., wenn ggT(a, n) = 1 gilt.

41 Verfahren und seine Korrektheit
41 Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit [e*d]%n = 1. A(lice) B(ob) öffentl. Schlüssel von B(ob) privat. Schlüssel von B(ob) (e, n) (d, n) "HALLO ..." "HALLO ..." Codierung f(x, (e,n)) = [x*e]%n f*(y, (d,n)) = [y*d]%n Codierung x0, x1, x2, ... y0, y1, y2, ... x0, x1, x2, ... Klartext Geheimtext Klartext Verschlüsselungsfunktion Entschlüsselungsfunktion Korrektheit: Die Entschlüsselung macht die Verschlüsselung rückgängig: x → [x * e]%n → [[x * e]%n * d]%n = [x * [e * d]%n]%n = [x * 1]%n = x Es muss hierzu folgende Schlüsselbedingung erfüllt sein: [e * d]%n = 1 d.h.: d ist modulares Inverses zu e bzgl. n.

42 Durchführung mit Python
42 Aufgabe: Eine Implementierung testen Erstelle die Datei chiffriersystemModularesMultiplizieren.py oder lade sie herunter (siehe inf- schule). Teste das Chiffriersystem mit selbst gewählten Beispielen. Dokumentiere die Ergebnisse. from chiffriersystemModulareMultiplikation import * # Vorgaben abc = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ' block = 1 oeffentlicherSchluessel = (7, 30) privaterSchluessel = (13, 30) # Verarbeitung quelltext = 'ASTERIX' quellcode = codierung(quelltext, block, abc) geheimcode = verschluesselung(quellcode, oeffentlicherSchluessel) entschluesseltercode = verschluesselung(geheimcode, privaterSchluessel) entschluesseltertext = decodierung(entschluesseltercode, block, abc) # Ausgaben print('Quelltext:') print(quelltext) print('Quellcode:') print(quellcode) print('Geheimcode:') print(geheimcode) print('entschlüsselter Code:') print(entschluesseltercode) print('entschlüsselter Text:') print(entschluesseltertext)

43 Geheimcodes knacken Codierung: Umwandlung von Zeichen in Zahlen
43 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 Verschlüsselung: öffentlicher Schlüssel (e, n) = (16, 33) Entschlüsselung: privater Schlüssel (d, n) = (..., ...) 24, 12, 15, 29, 23, 12, 13 Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26

44 Geheimcodes knacken Codierung: Umwandlung von Zeichen in Zahlen
44 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 Verschlüsselung: öffentlicher Schlüssel (e, n) = (781, 2828) 1893, 236, 1973, 1292, 1077, 2028, 2431 Entschlüsselung: privater Schlüssel (d, n) = (..., ...) Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26

45 Bestimmung des modularen Inversen
45 Ein naiver Ansatz besteht darin, der Reihe nach alle Zahlen durchzuprobieren, bis man das gewünschte Ergebnis gefunden hat. Beispiel: e = 16; n = 33 [16*1]%33 = 16; [16*2]%33 = 32; ...; [16*31]%33 = 1 Diesen naiven Ansatz kann man auch leicht implementieren: def modInv(e, n): gefunden = False d = 1 while d <= n and not gefunden: if (e * d) % n == 1: gefunden = True else: d = d + 1 if d > n: d = -1 return d Übung: Teste die Funktion mit selbst gewählten Beispielen. Nutze die Funktion modInv, um das modulare Inverse von 781 bzg zu bestimmen.

46 Bestimmung des modularen Inversen
46 Aufgabe: (a) Teste den Baustein mit großen Zahlen. Bestimme hierzu das modulare Inverse von a = bzgl. des Moduls n = (b) Bestimme zunächst mit dem Resultat aus (a) das modulare Inverse von b = 49 bzgl. des Moduls n = Bestimme anschließend das gesuchte modulare Inverse mit dem vorgegebenen Baustein. Welches Problem tritt hier auf? Hast du eine Vermutung, warum das Problem auftritt.

47 Bestimmung des modularen Inversen
47 def modInvMitAusgaben(e, n): gefunden = False d = 1 while d <= n and not gefunden: if d % == 0: print("Anzahl der Versuche: ", d) if (e * d) % n == 1: gefunden = True else: d = d + 1 if d > n: d = -1 return d >>> modInvMitAusgaben(49, ) Anzahl der Versuche: Anzahl der Versuche: Anzahl der Versuche: ... für 10 Millionen Überprüfungen benötigt man mehr als 1 Sekunde!

48 Bestimmung des modularen Inversen
48 Beispiel: d = 49 n = modInv(d, n) Um (= 107) Zahlen durchzuprobieren, benötigt ein Rechner derzeit mehr als 1s. Da das erwartete Ergebnis eine 54-stellige Zahl ist, wird der Rechner eine Zeit benötigen, die in der Größenordnung von 1047s liegt. Dies sind mehr als 1039 Jahre. Bedenkt man, dass das Universum ein Alter von etwa 1010 Jahre hat, dann zeigt sich, wie ungeeignet das naive Vorgehen ist. Verwendbarkeit: Für größere Zahlen ist der naive Algorithmus zur Berechnung des modularen Inversen unbrauchbar. Für die gezeigten Zahlen benötigt ein Rechner länger, als das Universum alt ist.

49 Vielfachsummensatz 49 Ein besseres Verfahren zur Bestimmung des modularen Inversen basiert auf folgendem Zusammenhang ("Vielfachsummensatz", "Lemma von Bézout", "Lemma von Bachet"): Vielfachsummensatz: Für je zwei natürliche Zahlen a und b gibt es ganze Zahlen x und y mit ggT(a,b)=x*a+y*b. Beispiele: a = 3; b = 4: ggT(3, 4) = 1 = (-1)*3 + 1*4 a = 6; b = 9: ggT(6, 9) = 3 = (-1)*6 + 1 * 9 a = 41; b = 192: ggT(41, 192) = 1 = 89*41 + (-19)*192

50 Erweiterter euklidischer Algorithmus
50 Gegeben: a = 884; b = 320 Gesucht: ggT(a, b) = x*a + y*b (1) 884 = 2* → 244 = *320 = (1* *320) - 2*(1* *884) = 1* *320 (2) 320 = 1* → 76 = *244 = (0* *320) - 1*(1* *320)) = 3* *884 (3) 244 = 3* → 16 = *76 = (1* *320) - 3*(3* *884) = 4* *320 (4) 76 = 4* → 12 = *16 = (3* *884) - 4*(4* *320) = 47* *884 (5) 16 = 1* → 4 = *12 = (4* *320) - 1*(47* *884) = 21* *320 (6) 12 = 3*4 + 0 Ergebnis: ggT(884, 320) = 4 = 21*884 + (- 58)*320

51 Implementierung 51 def erweiterterEuklidischerAlgorithmus(a, b):
aalt = a amitte = b xalt = 1 xmitte = 0 yalt = 0 ymitte = 1 while amitte != 0: q = aalt // amitte aneu = aalt - q * amitte xneu = xalt - xmitte * q yneu = yalt - ymitte * q xalt = xmitte xmitte = xneu yalt = ymitte ymitte = yneu aalt = amitte amitte = aneu print(amitte, '=', xmitte, '*', a, '+', ymitte, '*', b) return (aalt, xalt, yalt) Aufgabe: Teste die Implementierung des erweiterten Euklidischen Algorithmus..

52 Bestimmung des modularen Inversen
52 Mit Hilfe der Ausgaben des erweiterten euklidischen Algorithmus lässt sich das modulare Inverse bestimmen: Beispiel 1: Gesucht wird das modulare Inverse von a = 41 bzgl. m = 192. Python liefert: >>> erweiterterEuklidischerAlgorithmus(41, 192) (1, 89, -19) Umformungen: 1 = 89*41 + (-19)*192 1 - (-19)*192 = 89*41 [1 - (-19)*192]% 192 = [89*41]%192 [1 + 19*192]% 192 = [89*41]%192 1 = [89*41]%192 Ergebnis: b = 89

53 Bestimmung des modularen Inversen
53 Mit Hilfe der Ausgaben des erweiterten euklidischen Algorithmus lässt sich das modulare Inverse bestimmen: Beispiel 2: Gesucht wird das modulare Inverse von a = 17 bzgl. m = 192 . Python liefert: >>> erweiterterEuklidischerAlgorithmus(17, 192) (1, -79, 7) Umformungen: 1 = (-79)*17 + 7*192 1 - 7*192 = (-79)*17 1 - 7* *17 = ( )*17 1 + 10*192 = 113*17 [1 + 10*192]%192 = [113*17]%192 1 = [113*17]%192 Ergebnis: b = 113 =

54 Aufgabe 54 Beispiel 3: Gesucht wird das modulare Inverse von a = 7 bzgl. m = 30. Python liefert: >>> erweiterterEuklidischerAlgorithmus( , ) Umformungen: Ergebnis: b =

55 Bestimmung des modularen Inversen
55 Mit Hilfe der Ausgaben des erweiterten euklidischen Algorithmus lässt sich das modulare Inverse bestimmen. def modInv(a, m): (ggt, x, y) = erweiterterEuklidischerAlgorithmus(a, m) if ggt > 1: return -1 else: if x < 0: x = x + m return x Teste die Implementierung insbesondere für große Zahlen: d = 49 m = modInv(d, m) Welche Konsequenzen ergeben sich hieraus für die Sicherheit des Chiffrierverfahrens mit modularer Multiplikation?

56 Sicherheit 56 (e, n) f(x, (e,n)) = [x*e]%n (?, n) ??? A(lice) Klartext f*(y, (d,n)) [y*d]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext Verschlüsselungsfunktion Entschlüsselungsfunktion Codierung B(ob) pivat. Schlüssel von B(ob) Mr(s) X Schlüsselerzeugung: Wähle n größer als die maximale Codezahl. Wähle e mit e <n. Bestimme d mit [e*d]%n = 1. Sicherheit: Das "multiplikative" Chiffrierverfahren ist nicht sicher, da man aus dem öffentlichen Schlüssel mit Hilfe des erweiterten euklidischen Algorithmus den privaten Schlüssel recht schnell bestimmen kann. Die "Unsicherheit" basiert hier also darauf, dass man ein schnelles Verfahren gefunden hat, um das modulare Inverse zu einer Zahl zu bestimmen.

57 Verschlüsselung mit modularer Potenz
Teil 5 57 Verschlüsselung mit modularer Potenz

58 Verschlüsseln d. modulares Rechnen
58 modulares Addieren modulares Multiplizieren modulares Potenzieren Verschlüsselung mit öffentl. Schlüssel (e, n) Verschlüsselung mit öffentl. Schlüssel (e, n) Verschlüsselung mit öffentl. Schlüssel (e, n) x → [x + e]%n x → [x * e]%n x → [x ** e]%n Entschlüsselung mit privat. Schlüssel (d, n) Entschlüsselung mit privat. Schlüssel (d, n) Entschlüsselung mit privat. Schlüssel (d, n) y → [y + d]%n y → [y * d]%n y → [z ** d]%n

59 Verschlüsseln d. modulares Potenzieren
59 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 A,S,T,E,R,I,X 01,19,20,05,18,09,24 Verschlüsselung: öffentlicher Schlüssel (e, n) = (13, 77) (01 ** 13) % 77 = 01 (19 ** 13) % 77 = (24 ** 13) % 77 = 52 01,19,20,05,18,09,24 01,61,...,...,...,...,52 Entschlüsselung: privater Schlüssel (d, n) = (37, 77) (01 ** 37) % 77 = 01 (61 ** 37) % 77 = (52 ** 37) % 77 = 24 01,61,...,...,...,...,52 01,19,20,05,18,09,24 Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26 01,19,20,05,18,09,24 A,S,T,E,R,I,X

60 Verschlüsseln d. modulares Potenzieren
60 Aufgabe: Führe die erforderlichen Berechnungen selbst durch. Verschlüsselung: öffentlicher Schlüssel (e, n) = (13, 77) (01 ** 13) % 77 = 01 (19 ** 13) % 77 = (24 ** 13) % 77 = 52 01,19,20,05,18,09,24 01,61,...,...,...,...,52 Entschlüsselung: privater Schlüssel (d, n) = (37, 77) (01 ** 37) % 77 = 01 (61 ** 37) % 77 = (52 ** 37) % 77 = 24 01,61,...,...,...,...,52 01,19,20,05,18,09,24 >>> 52 ** 37 >>> % 77 24

61 Schwierigkeiten beim Potenzieren
61 Aufgabe: Führe das Verfahren mit modularer Potenz auch mit folgenden Daten durch. Welche Schwierigkeit tritt dabei auf? (a) Quelltext: ASTERIX Codierung: wie oben Blocklänge: 3 öffentlicher Schlüssel: ( , ) privater Schlüssel: (377911, ) (b) Blocklänge: 4 öffentlicher Schlüssel: ( , ) privater Schlüssel: ( , )

62 Schwierigkeiten beim Potenzieren
62 Beim Rechnen mit Potenzen erhält man große Zahlen: >>> 24 ** 13 >>> % 77 52 >>> 52 ** 37 >>> % 77 24 Wenn die Ausgangszahlen jetzt ebenfalls groß sind, dann muss das Ausführsystem riesige Zahlen verwalten. Python liefert bei solch großen Zahlen erst einmal keine Ergebnisse. >>> ** ???

63 Modulares Potenzieren
63 Bei modularen Potenzen kann man zuerst die Potenz berechnen und anschließend den modularen Rest. [3 * 3 * 3 * 3 * 3 * 3]% 5 = [729]%5 = 4 Günstiger ist es, die Modulbildung aber nach jedem Rechenschritt durchzuführen. [3 * 3 * 3 * 3 * 3 * 3]% 5 = [[[[[3 * 3]%5 * 3]%5 * 3]%5 * 3]%5 * 3]%5 = [[[[ * 3]%5 * 3]%5 * 3]%5 * 3]%5 = [[[ * 3]%5 * 3]%5 * 3]%5 = [[ * 3]%5 * 3]%5 = [ * 3]%5 = 4

64 Modulares Potenzieren
64 Teste die Funktion modpot. Überzeuge dich mit geeigneten Ausgaben, dass die zwischenzeitlich berechneten Zahlen „klein“ bleiben. def modpot(x, y, m): pot = 1 zaehler = 0 while zaehler < y: pot = (pot * x) % m zaehler = zaehler + 1 return pot Teste modpot auch mit großen Zahlen. >>> modpot(11920, , ) >>> modpot( , , )

65 Schnelles Potenzieren
65 So … 3 9 27 81 243 oder so? 3 9 81 6561

66 Schnelles Potenzieren
66 3 9 81 6561 243 Darstellung in Tabellenform: x y pot 3 13 1 12 1*3 = 3 9 6 81 2 3*81 = 243 6561 243*6561 =

67 Schnelles modulares Potenzieren
67 3 4 1 %5 Darstellung in Tabellenform: x y pot 3 13 1 12 [1*3]%5 = 3 [3*3]%5 = 4 6 [4*4]%5 = 1 2 [3*1]%5 = 3 [1*1]%5 = 1

68 Schnelles modulares Potenzieren
68 x y pot 3 13 1 12 [1*3]%5 = 3 [3*3]%5 = 4 6 [4*4]%5 = 1 2 [3*1]%5 = 3 [1*1]%5 = 1

69 Schnelles modulares Potenzieren
69 def modpot(x, y, m): pot = 1 while y > 0: if y % 2 == 1: pot = (pot * x) % m y = y - 1 else: x = (x * x) % m y = y // 2 return pot Aufgabe: >>> modpot(11920, , )

70 Durchführung mit Python
70 Aufgabe: Lade die Datei chiffriersystemModularePotenz.py (siehe inf-schule) herunter. Diese Datei enthält eine ganze Reihe von Funktionen zur Implementierung des RSA-Verfahrens. Mit den Funktionen der Implementierung kannst du jetzt das RSA-Verfahren durchspielen. Probiere das mit selbst gewählten Daten aus. Dokumentiere die Ergebnisse. Zur Kontrolle: Vergleiche die erzielten Ergebnisse mit denen, die CrypTool (mit passenden Einstellungen) liefert.

71 Erzeugung der Schlüssel
71 Vorbereitung: Wähle zwei verschiedene Primzahlen p und q. öffentlicher Schlüssel: Berechne n = p*q. Berechne φ(n) = (p-1)*(q-1). Wähle eine Zahl e mit 1 < e < φ(n) , die teilerfremd zu φ(n) ist. Der öffentliche Schlüssel ist (e, n). ("Vernichte p, q, φ(n).") privater Schlüssel: Berechne d so, dass [e*d]%φ(n) = 1 ist. Der private Schlüssel ist (d, n). Beispiel: p = 7; q = 11 n = 77 φ(n) = 60 z. B. e = 13 (13, 77) d = 37 (37, 77)

72 Korrektheit des RSA-Verfahren
72 (e, n) f(x, (e,n)) = [xe]%n (d, n) x0, x1, x2, ... A(lice) Klartext f*(y, (d,n)) [yd]%n öffentl. Schlüssel von B(ob) y0, y1, y2, ... Geheimtext RSA-Verschlüsselungsfunktion RSA- Entschlüsselungsfunktion "HALLO ..." Codierung B(ob) privat. Schlüssel von B(ob) RSA-Schlüsselerzeugung: Wähle zwei verschiedene Primzahlen p und q. Berechne n = pq und (n) = (p-1)(q-1). Wähle e mit 1 < e < (n) und ggT(e,(n)) = 1. Bestimme d mit [cd]%(n) = 1. Korrektheit: Die Entschlüsselung macht die Verschlüsselung rückgängig: x → [xe]%n → [([xe]%n)d]%n = [x(e*d)]%n = [x]%n = x Es muss hierzu folgende Schlüsseleigenschaft erfüllt sein: [x(e*d)]%n = x für alle x < n

73 Korrektheit des RSA-Verfahren
73 Beh.: [x(e * d)]%n = x für alle x < n Begr.: Schritt 1: Es gilt n = p*q mit zwei verschiedenen Primzahlen p und q. Wir zeigen: [x(e*d)]%p = [x]%p und [x(e*d)]%q = [x]%q für alle Zahlen x < n Es reicht, den Nachweise für eine der beiden Primzahlen p und q zu führen. Der Nachweis für die andere Primzahl verläuft dann völlig analog. Wir betrachten im Folgenden die Primzahl p. Fall 1: p und x sind nicht teilerfremd. Da p eine Primzahl ist, muss in diesem Fall p ein Teiler von x sein. Die Primzahl p muss dann auch ein Teiler der Potenz x(e*d) sein. Es folgt: [x]%p = 0 und [x(e*d)]% p = 0 Also: [x(e*d)]%p = [x]%p Fall 2: p und x sind teilerfremd. Nach dem kleinen Fermatschen Satz git dann: [x(p-1)]%p = 1 Nach der Konstruktion der Schlüssel gilt: [e*d]%φ(n) = 1 Da φ(n) = (p-1)*(q-1), gibt es also eine Zahl a mit e*d = a*(p-1)*(q-1)+1. ... Satz (Kleiner Fermatscher Satz): Sei p eine Primzahl und a eine natürliche Zahl, die kein Vielfaches von p ist. Dann gilt: [a(p-1)]%p = 1

74 Korrektheit des RSA-Verfahren
74 ... Jetzt können wir folgende Umformungen vornehmen: [x(e*d)]%p = [x(a*(p-1)*(q-1)+1)]%p = [x(a*(p-1)*(q-1))*x]%p = [x(a*(p-1)*(q-1))]%p * [x]%p = [([x(p-1)]%p)(a*(q-1))]%p * [x]%p = [1(a*(q-1))]%p * [x]%p = 1 * [x]%p = [x]%p Damit ist die Behauptung von Schritt 1 gezeigt. Schritt 2: Aus [x(e*d)]%p = [x]%p und [x(e*d)]%q = [x]%q (für alle Zahlen x < n) können wir jetzt (mit dem Satz über modulare Gleichheit bzgl. Primzahlen) schließen: [x(e*d)]%(p*q) = [x]%(p*q) Wegen n = p*q und x < n gilt dann: [x(e*d)]%n = x

75 Sicherheit 75 (e, n) f(x, (e,n)) = [xe]%n (?, n) ??? A(lice) Klartext f*(y, (d,n)) [yd]%n y0, y1, y2, ... Geheimtext RSA-Verschlüsselungsfunktion RSA- Entschlüsselungsfunktion Codierung RSA-Schlüsselerzeugung: Wähle zwei verschiedene Primzahlen p und q. Berechne n = pq und (n) = (p-1)(q-1). Wähle e mit 1 < e < (n) und ggT(e,(n)) = 1. Bestimme d mit [cd]%(n) = 1. B(ob) Mr(s) X öffentl. Schlüssel von B(ob) privat. Schlüssel von B(ob) Sicherheit: Die Sicherheit des RSA-Verfahrens hängt davon ab, ob man aus dem öffentlichen Schlüssel (e, n) den privaten Schlüssel (d, n) (effizient) bestimmen kann.

76 Geheimcodes knacken Codierung: Umwandlung von Zeichen in Zahlen
76 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 Verschlüsselung: öffentlicher Schlüssel (e, n) = (19, 65) 48, 9, 60, 38, 60, 0, 58, 47, 31, 60, 59, 59, 60, 0, 1, 31, 59, 0, 58, 1, 38, 38, 9, 60, 14 Entschlüsselung: privater Schlüssel (d, n) = (..., ...) Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26

77 Geheimcodes knacken Codierung: Umwandlung von Zeichen in Zahlen
77 Codierung: Umwandlung von Zeichen in Zahlen ' ' → 00 'A' → 'Z' → 26 Verschlüsselung: öffentlicher Schlüssel (e, n) = (113, 6887) 6613, 5456, 1378, 2773, 1646, 5581, 4072 Entschlüsselung: privater Schlüssel (d, n) = (..., ...) Decodierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26

78 Geheimcodes knacken 78 öffentlicher Schlüssel (e, n) = ( , ) privater Schlüssel (d, n) = (..., ...) Codierung: Umwandlung von Zahlen in Zeichen ' ' → 00 'A' → 'Z' → 26 ,

79 Angriff auf das RSA-Verfahren
79 (e, n) f(x, (e,n)) = [xe]%n (?, n) ??? A(lice) Klartext f*(y, (d,n)) [yd]%n y0, y1, y2, ... Geheimtext RSA-Verschlüsselungsfunktion RSA- Entschlüsselungsfunktion Codierung RSA-Schlüsselerzeugung: Wähle zwei verschiedene Primzahlen p und q. Berechne n = pq und (n) = (p-1)(q-1). Wähle e mit 1 < e < (n) und ggT(e,(n)) = 1. Bestimme d mit [cd]%(n) = 1. B(ob) öffentl. Schlüssel von B(ob) privat. Schlüssel von B(ob) Beispiel (Aufgabe): n = 65 -> p = 5 und q = 13 Aus den beiden Primzahlen p und q kann Mr(s). X die Zahl φ(n) = (p-1) * (q-1) berechnen. Beispiel (Aufgabe 1): p = 5 und q = 13 -> φ(n) = 48 Mr(s). X weiß zudem, dass die Zahl d modulares Inverses von e bzgl. φ(n) ist. Mit dem erweiterten euklidischen Algorithmus kann Mr(s). X diese Zahl d bestimmen. Beispiel (Aufgabe 1): e = 19 und φ(n) = 48: [19*d]%48 = 1 -> d = 43 Mr(s). X kennt jetzt den privaten Schlüssel und kann den Geheimtext entschlüsseln.

80 Sicherheit des RSA-Verfahrens
80 (e, n) f(x, (e,n)) = [xe]%n (?, n) ??? A(lice) Klartext f*(y, (d,n)) [yd]%n y0, y1, y2, ... Geheimtext RSA-Verschlüsselungsfunktion RSA- Entschlüsselungsfunktion Codierung RSA-Schlüsselerzeugung: Wähle zwei verschiedene Primzahlen p und q. Berechne n = pq und (n) = (p-1)(q-1). Wähle e mit 1 < e < (n) und ggT(e,(n)) = 1. Bestimme d mit [cd]%(n) = 1. B(ob) öffentl. Schlüssel von B(ob) pivat. Schlüssel von B(ob) Sicherheit: Die Sicherheit des RSA-Verfahrens hängt davon ab, ob man die Zahl n in vertretbarer Zeit in ihre Primfaktoren p und q zerlegen kann. Bis heute gibt es keine schnellen Algorithmen, um eine Zahl in ihre Primfaktoren zu zerlegen. Das RSA-Verfahren ist bei groß gewählten Primzahlen recht sicher, da man aus dem öffentlichen Schlüssel den privaten Schlüssel bisher nicht in angemessener Zeit bestimmen kann.

81 Teil 6 81 Primzahlalgorithmen

82 Primzahltest 82 Zur Durchführung des RSA-Verfahrens benötigt man große Primzahlen. Man wählt heute Primzahlen, die mit mindestens 2048 Bit dargestellt werden. Das sind Zahlen in der Größenordnung 22048, also Zahlen mit mehr als 600 Dezimalstellen. >>> 2**2048 >>> len(str(2**2048)) 617 Zur Bestimmung großer Primzahlen geht man wie folgt vor. Man erzeugt eine Zufallszahl im gewünschten Größenbereich und testet, ob es sich um eine Primzahl handelt. Hierzu benötigt man geeignete Primzahltests. Da es sehr viele Primzahlen im gewünschten Bereich gibt, muss man in der Regel nicht allzu viele Zahlen testen.

83 Primzahlen 83 Primzahlen sind natürliche Zahlen, die nur durch 1 und sich selbst ohne Rest teilbar sind. Beispiele: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, ... Aufgabe: Aus der Primzahleigenschaft ergibt sich direkt ein einfacher Algorithmus, mit dem man bei einer natürlichen Zahl n überprüfen kann, ob es sich um eine Primzahl handelt. (a) Formuliere den Algorithmus in Struktogrammform. (b) Implementiere und teste den Algorithmus. (c) Entwickle Möglichkeiten zur Verbesserungen des einfachen Algorithmus.

84 Ein einfaches Testverfahren
84 def primzahl(n): if n <= 2: if n < 2: prim = False else: prim = True if n % 2 == 0: faktorgefunden = True faktorgefunden = False t = 3 while t*t <= n and not faktorgefunden: if n % t == 0: t = t + 2 prim = not faktorgefunden return prim

85 Ein einfaches Testverfahren
85 primzahlen = [ 11, 101, 1009, 10007, 100003, , , , , , , , , , , , , , , , , ...] def primzahl(n): ... from time import * for p in primzahlen: t1 = clock() ergebnis = primzahl(p) t2 = clock() t = t2 - t1 print("Primzahl: ", p, "Rechenzeit: ", t)

86 Laufzeitverhalten 86 >>>
Primzahl: 11 Rechenzeit: e-06 Primzahl: 101 Rechenzeit: e-06 Primzahl: Rechenzeit: e-05 Primzahl: Rechenzeit: e-05 Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: ... Aufgabe: Schätze ab, wie lange eine Überprüfung einer 600-stelligen Primzahl in etwa dauert.

87 Probabilistische Testverfahren
87 In der Praxis benutzt man heute oft sogenannte probabilistische Testverfahren, da sie sehr effizient arbeiten. Probabilistischen Testverfahren funktionieren nach dem folgenden Prinzip: Bei Übergabe einer natürlichen Zahl n erhält man als Rückgabe entweder "n ist keine Primzahl" oder "n ist wahrscheinlich eine Primzahl". Diese Testverfahren liefern also keine absolute Gewissheit, wenn sie das Ergebnis "n ist wahrscheinlich eine Primzahl" produzieren. Die übergebene Zahl n kann mit einer bestimmten Wahrscheinlichkeit auch keine Primzahl sein. Allerdings ist diese Wahrscheinlichkeit sehr gering, so dass man die Unsicherheit oft in Kauf nimmt. Eines dieser probabilistischer Testverfahren ist das Miller-Rabin-Verfahren, das im Folgenden getestet werden soll. Beachte, dass die Wiederholungszahl 20 (s.u.) die Fehlerwahrscheinlichkeit beeinflusst. Setzt man diese Wiederholungszahl auf einen größeren Wert, so nimmt die Fehlerwahrscheinlichkeit ab.

88 Miller-Rabin-Test 88 import random def miller_rabin_pass(a, n):
d = n - 1 s = 0 while d % 2 == 0: d = d >> 1 s = s + 1 a_to_power = pow(a, d, n) if a_to_power == 1: return True for i in range(s-1): if a_to_power == n - 1: a_to_power = (a_to_power * a_to_power) % n return a_to_power == n - 1 def miller_rabin_test(n): for repeat in range(20): a = 0 while a == 0: a = random.randrange(n) if not miller_rabin_pass(a, n): return False

89 Laufzeitverhalten 89 >>>
Primzahl: 11 Rechenzeit: Primzahl: 101 Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit: Primzahl: Rechenzeit:

90 Primfaktorzerlegung 260 2 * 2 * 5 * 13 90
Eine der wichtigsten Eigenschaften von Primzahlen ist, dass sie als Bausteine der natürlichen Zahlen angesehen werden können. Satz: Jede natürliche Zahl lässt sich als Produkt von Primzahlen schreiben. Diese Darstellung ist bis auf die Reihenfolge der Faktoren eindeutig. Beispiel: 260 = 2*2*5*13 = 22*5*13 Man nennt die Primzahlen, die in einer Produktdarstellung einer gegebenen Zahl vorkommen, auch Primfaktoren der Zahl. Das Faktorisierungsproblem besteht darin, eine vorgegebene Zahl in ein Produkt aus Primfaktoren zu zerlegen.

91 Aufgabe 91 (a) Bei kleineren Zahlen kann man eine Primfaktorzerlegung oft direkt angeben. Bestimme eine Primfaktorzerlegung von n = 48 und n = 100. (b) Bei größeren Zahlen sollte man systematisch vorgehen, um die Primfaktoren zu bestimmen. Bestimme eine Primfaktorzerlegung von n = 221 und n = 585. (c) Entwickle zunächst einen Algorithmus zur Primfaktorzerlegung. Beschreibe in einem ersten Schritt in Worten das Verfahren, das du zur Primfaktorzerlegung von Zahlen benutzt. Beschreibe das Verfahren anschließend mit einem Struktogramm. Entwickle dann ein Programm zur Primfaktordarstellung. Hinweis: In Python bietet es sich an, eine Funktion primfaktoren(n) zu erstellen, die die Liste der Primfaktoren zurückgibt.

92 Ein einfaches Faktorisierungsverfahren
92 ALGORITHMUS primfaktoren(n): initialisiere die Liste faktoren: faktoren = [] initialisiere die Hilfsvariable z: z = n SOLANGE z > 1: bestimme den kleinsten Primfaktor p von z mit Probedivisionen füge p in die Liste faktoren ein z = z // p Rückgabe: faktoren # Übergabe: n = 51 # Initialisierung faktoren = [] {faktoren -> []} z = n {z -> 51} # Probedivisionen z % 2 -> 1 z % 3 -> 0 # Aktualisierung p = z {p -> 3} faktoren = faktoren + [p] {faktoren -> [3]} z = z // p {z -> 17} z % 3 -> 2 z % 4 -> 1 z % 5 -> 2 p = z {p -> 17} faktoren = faktoren + [p] {faktoren -> [3, 17]} z = z // p {z -> 1} # Rückgabe: [3, 17] Aufgabe: Bestimme mit (einer geeigneten Implementierung) der Funktion primfaktoren(n) die Primfaktorzerlegung der beiden Zahlen und Was stellst du fest? Stelle eine Vermutung auf, warum es hier zu einem unterschiedlichen Laufzeitverhalten kommt.

93 Laufzeitmessungen 93 from faktorisierung import primfaktoren from time import * testzahlen = [...] for z in testzahlen: t1 = clock() ergebnis = primfaktoren(z) t2 = clock() t = t2 - t1 print("Zahl: ", z) print("Primfaktoren:", ergebnis) print("Rechenzeit: ", t) print() testzahlen = [ 11, 101, 1009, 10007, 100003, , , , , , , , , , , , , , , , ...] Hinweis: Um Gesetzmäßigkeiten herauszufinden, sollte man systematisch vorgehen. Aufgabe: Führe die Messungen durch. Kannst du anhand der Zahlen erste Zusammenhänge erkennen? Kannst du Prognosen erstellen, wie lange man wohl bis zum nächsten Ergebnis warten muss?

94 Zusammenhänge und Prognosen
94 Gesetzmäßigkeit: Wenn man die Anzahl der Stellen der Ausgangszahl um 2 erhöht, dann erhöht sich die Laufzeit um den Faktor 10. Jede zusätzliche Stelle bei der Ausgangszahl führt also dazu, dass die Laufzeit mit dem Faktor √10 multipliziert wird. Es handelt sich hier um ein exponentielles Wachstumsverhalten, das man mathematisch mit einer Exponentialfunktion beschreiben kann: Wenn k die Anzahl der Stellen der Ausgangszahl angibt, dann erhält man eine Laufzeit vom Typ L(k) = c*(√10)k mit einer Konstanten c. Prognose: Wenn die Zahl 100 Stellen haben soll, also 88 Stellen mehr als eine 12-stellige Zahl, so benötigt man nach der gefundenen Gesetzmäßigkeit 1044-mal so lange wie bei der 12-stelligen Zahl - also etwa Sekunden. ... Zahl: Primfaktoren: [ ] Rechenzeit: Zahl: Primfaktoren: [ ] Rechenzeit: Zahl: Primfaktoren: [ ] Rechenzeit: Zahl: Primfaktoren: [ ] Rechenzeit: Zahl: Primfaktoren: [ ] Rechenzeit:

95 Fazit 95 Algorithmen spielen bei der Entwicklung von Chiffriersystemen eine große Rolle. Im Fall des RSA-Verfahrens benötigt man einerseits gute Algorithmen, um das Verfahren überhaupt effizient durchführen zu können (z. B. schnell ein modulares Inverses bestimmen; schnell eine modulare Potenz bestimmen). Andererseits ist das Verfahren so angelegt, dass bestimmte Operation mit den bisher bekannten Algorithmen mit vertretbarem Rechenaufwand nicht durchgeführt werden können.

96 Lehrplan - Leistungsfach
96 Ziel ist es, das RSA- Verfahren als eines der klassischen asymmetrischen Verschlüsselungs- verfahren genauer zu untersuchen, um die Funktionsweise dieses Verfahrens zu verstehen. Die Vorgehensweise folgt einem Vorschlag von Witten und Schulz, der in den folgenden Artikeln beschrieben wird: H. Witten, R.-H. Schulz: RSA & Co. in der Schule, Teil1. LOG IN 140 S. 45 ff. H. Witten, R.-H. Schulz: RSA & Co. in der Schule, Teil2. LOG IN 143 S. 50 ff. Lehrplan für das Leistungsfach

97 Exkurs: GnuPG-Schlüssel
Teil 7 97 Exkurs: GnuPG-Schlüssel

98 Schlüsselerzeugung mit GnuPG
98 C:\>gpg --gen-key gpg (GnuPG) ; Copyright (C) 2008 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Bitte wählen Sie, welche Art von Schlüssel Sie möchten: (1) RSA und RSA (voreingestellt) (2) DSA und Elgamal (3) DSA (nur unterschreiben/beglaubigen) (4) RSA (nur signieren/beglaubigen) Ihre Auswahl? 1 RSA Schlüssel können zwischen 1024 und 4096 Bits lang sein. Welche Schlüssellänge wünschen Sie? (2048) Die verlangte Schlüssellänge beträgt 2048 Bit .+++++ gpg: Schlüssel 468BA4E2 ist als uneingeschränkt vertrauenswürdig gekennzeichnet Öffentlichen und geheimen Schlüssel erzeugt und signiert.

99 Export des öffentlichen Schlüssels
99 C:\>gpg --armor --output bob_public_key.asc --export "Bob Happy" -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v (MingW32) mQENBFn6wOcBCADHS0ukFSGLtypNx3m6FuWi179EYncoEmbOKM17i1YwJbVa4RFk iHypzLGj/QwlwiTWktT4atiroiieFNm6c0FLDM7NsYyJZA+7K3ikGEKcSKjUINhQ Ns5UvajeYld/nI1/qOJKyE78UEI/E9lGV7oFP4D1vpyZgkheV7vKUq7pYlbBPVUr UPOyDF5UWs3z5ZQiiasoqij6+8wt6Lj+BS9IoyCtdQxGDLE5X+FxN7gz2FbinZSl yC6BwfzpKMY++dKy28vs+E0YmCtAspMSjNLGH8momeIKfqndeUiI6tB4FRxZl8iW AFx8RxyzSTfl27kV653dErTindZae86PAt2DABEBAAG0HkJvYiBIYXBweSAoLi4u KSA8Ym9iQGhhcHB5LmRlPokBPwQTAQIAKQUCWfrA5wIbAwUJACeNAAcLCQgHAwIB BhUIAgkKCwQWAgMBAh4BAheAAAoJEKUZ1x9Gi6Tiai0IAMKGhuX9wi3an5qwfCmt Kwaybw60oVKmZF5rgFRJfnQgb2bCc3NpSI45i/Cc36pnFR/TtIbmPgm6zhjSdC92 QwqqBByJ/6f/pXjWU2F6k2Y6mEqFXkkPsT5SeTHHiqqKqPa67KChOsRRQqBqw5uN 7/8TvsCKpMj+HzTaULgQG7+2wF4mgyZvJeSOKaXxaUCPEJ/KLVsTnKjpbqDBm4g5 I3I2mCR+RT+r8oRbSYv45+wmtiUy6Na4VJJeNWpfQNoneXP+nkZbYURPbHkHFFvB Kw/O7XARium8qajrQrPntrJd7TniIv3CyTS4vJIiSnSjulpOvdzxgI6Qs1HlyVDS T3i5AQ0EWfrA5wEIAMxGrQYMcyJuN0Sz+2JulPcuqXb9Gd7DVkxojUIMBJN5IvOQ vyT30fKymx8CIJxn58dlXQhL1yLawDV9t88wbFpUWRSAYP6GTuDb7GkIqG3xt00n n4kLxjFipUn8RqMtrnojGgELXSpInkt+gP9lfQBlrKGKr4pTMJ0qamKIl/LOjEyZ uCj7T4S2XiCCWBu8NDlXwjHk1cTWdQ/f8Zm2ZZVvQlsBIKszg9GSY+a4pxPOAKWM JHTQnoZDjzzQC3iFsrBkzcwFS3Dbn1TfNoY9nFhKeI3FbBum4VbTKwsHArtsfe8B HpB7y1wOri3QhsqoXNv4ER9qNpRbuSZN5/bLbSkAEQEAAYkBJQQYAQIADwUCWfrA 5wIbDAUJACeNAAAKCRClGdcfRouk4t2cCACASRW5Vn8aa3NDyG4rEiTBFr98btE6 IYUwEi30kPOEo+rVwjrjfh0tH7uk0o1uWmMQWgV2J2ai18QS1/jucFka8yU75vpR bRgWD6JBj7o5gLNrvxA8/cQq/ZHRT/doDneevwJDvObCZBlPBxZCveiSxWJa4G+a KPjt+CFJ/gWlIwVLsldpEwEV/XX5a7DN+wuxvNVaFnCU2w33gVPLZF6YX4jK4iOh Qb/9wUQYrgpNDUOYWb1ZBB5FUIeltAQRc/VRYtP48PJbat6SBEg59Zb/OSKf2mSJ 1x09W4RPVjO5FPSGEUrAeipk3QUd3pIKyEj/8tjrGJ52h3YV10T4AtGG =dF2J -----END PGP PUBLIC KEY BLOCK-----

100 Blick hinter die Kulissen
100 C:\>gpg --with-key-data --list-keys 0x468BA4E2 tru::1: : :3:1:5 pub:u:2048:1:A519D71F468BA4E2: : ::u:::scESC: pkd:0:2048:00C74B4BA415218BB72A4DC779BA16E5A2D7BF CE28CD7B8B563025B55AE CA9CCB1A3FD0C25C224D692D4F86AD8ABA2289E14D9BA73414B0CCECDB18C89640FBB2B78A418429C48A8D420D85036CE54BDA8DE62577F9C8D7FA8E24AC84EFC50423F13D94657BA053F80F5BE9C E57BBCA52AEE96256C13D552B50F3B20C5E545ACDF3E AB28AA28FAFBCC2DE8B8FE052F48A320AD750C460CB1395FE17137B833D856E29D94A5C82E81C1FCE928C63EF9D2B2DBCBECF84D18982B40B293128CD2C61FC9A899E20A7EA9DD794888EAD078151C5997C896005C7C471CB34937E5DBB915EB9DDD12B4E29DD65A7BCE8F02DD83: pkd:1:17:010001: uid:u:::: ::AE597EF00F11C73ABF897B7E94E60C7A8470A6DC::Bob Happy (...) sub:u:2048:1:4D3A6B2FC3D4614A: : :::::e: pkd:0:2048:00CC46AD060C73226E3744B3FB626E94F72EA976FD19DEC3564C688D420C F390BF24F7D1F2B29B1F02209C67E7C7655D084BD722DAC0357DB7CF306C5A FE864EE0DBEC6908A86DF1B74D279F890BC63162A549FC46A32DAE7A231A010B5D2A489E4B7E80FF657D0065ACA18AAF8A53309D2A6A628897F2CE8C4C99B828FB4F84B65E BBC343957C231E4D5C4D6750FDFF199B665956F425B0120AB3383D19263E6B8A713CE00A58C2474D09E86438F3CD00B7885B2B064CDCC054B70DB9F54DF36863D9C584A788DC56C1BA6E156D32B0B0702BB6C7DEF011E907BCB5C0EAE2DD086CAA85CDBF8111F6A36945BB9264DE7F6CB6D29:

101 Blick hinter die Kulissen
101 n_hex = '0x00C74B4BA415218BB72A4DC779BA16E5A2D7BF CE28CD7B8B563025B55AE CA9CCB1A3FD0C25C224D692D4F86AD8ABA2289E14D9BA73414B0CCECDB18C89640FBB2B78A418429C48A8D420D85036CE54BDA8DE62577F9C8D7FA8E24AC84EFC50423F13D94657BA053F80F5BE9C E57BBCA52AEE96256C13D552B50F3B20C5E545ACDF3E AB28AA28FAFBCC2DE8B8FE052F48A320AD750C460CB1395FE17137B833D856E29D94A5C82E81C1FCE928C63EF9D2B2DBCBECF84D18982B40B293128CD2C61FC9A899E20A7EA9DD794888EAD078151C5997C896005C7C471CB34937E5DBB915EB9DDD12B4E29DD65A7BCE8F02DD83' e_hex = '0x010001' print('Anzahl der Bits von n: ', 4*len(str('C74B4BA415218BB72A4DC779BA16E5A2D7BF CE28CD7B8B563025B55AE CA9CCB1A3FD0C25C224D692D4F86AD8ABA2289E14D9BA73414B0CCECDB18C89640FBB2B78A418429C48A8D420D85036CE54BDA8DE62577F9C8D7FA8E24AC84EFC50423F13D94657BA053F80F5BE9C E57BBCA52AEE96256C13D552B50F3B20C5E545ACDF3E AB28AA28FAFBCC2DE8B8FE052F48A320AD750C460CB1395FE17137B833D856E29D94A5C82E81C1FCE928C63EF9D2B2DBCBECF84D18982B40B293128CD2C61FC9A899E20A7EA9DD794888EAD078151C5997C896005C7C471CB34937E5DBB915EB9DDD12B4E29DD65A7BCE8F02DD83'))) print('Anzahl der Bits von e: ', 4*len(str('0001'))+1) n = int(n_hex, 16) e = int(e_hex, 16) print('n: ', n) print('e: ', e) print('Anzahl der Stellen von n: ', len(str(n)))

102 Blick hinter die Kulissen
102 >>> Anzahl der Bits von n: 2048 Anzahl der Bits von e: 17 n: e: Anzahl der Stellen von n: 617

103 Literaturhinweise 103 Folgende Materialien wurden hier benutzt:
H. Witten, R.-H. Schulz: RSA & Co. in der Schule, Teil1. LOG IN 140 S. 45 ff H. Witten, R.-H. Schulz: RSA & Co. in der Schule, Teil2. LOG IN 143 S. 50 ff K. Merkert:


Herunterladen ppt "Das RSA-Verfahren Klaus Becker 2017."

Ähnliche Präsentationen


Google-Anzeigen