len(Zeichenkette)
.Das Ver- und Entschlüsseln von Nachrichten wird schon seit der Antike betrieben. Folgende Übersicht zeigt eine mögliche Einteilung der bestehenden Verschlüsselungs-Verfahren:
Auf dieser Seite betrachten wir ein kleine Auswahl von symmetrischen Verschlüsselungsverfahren:
Folgende Begriffe solltest du kennen:
Die Caesar-Verschlüsselung ist eine sehr einfache Form der monoalphabetischen Substitution. Bei der Substitution werden Buchstaben durch andere Buchstaben ersetzt (lat. substituere = „ersetzen“). Monoalphabetisch ist sie deshalb, weil sie nur ein (mono) Geheim-Alphabet benutzt. Bei der Caesar-Verschlüsselung ergibt sich das Geheimalphabet durch Verschiebung. Ist der Schlüssel 3, so wird jeder Buschstabe um 3 Stellen verschoben: Was im Geheim-Alphabet ein D ist, ist im richtigen Alphabet ein A usw.:
Der Name der Caesar-Verschlüsselung geht auf den römischen Feldherrn Gaius Julius Caesar zurück, der diese Methode zur Verschlüsselung vertaulicher Botschaften benutzte. Sicher ist die Methode heute keineswegs: Am Geheimtext lässt sich anhand von Mustern leicht erkennen, dass es sich um ein Substitutions-Verfahren mit Verschiebung des Alphabets handelt. Und es sind nur 25 verschiedene Schlüssel (Verschiebewerte) möglich. So geht es sehr schnell, diese durchzuprobieren und auf den richtigen Schlüssel zu kommen.
Programmiere einen Verschlüsselsungs-Algorithmus mit python!
Wenn du keine Idee hast, wie das gehen könnte: Lies folgende Schritte genau durch und überlege für jede Code-Zeile, ob du sie verstehst.
Der Output zu den Codebeispielen (zum Beispiel das, was durch die Funktion print()
ausgegeben wird) folgt jeweils auf den Code: Nach >>>
.
Wir importieren die Klasse string
für Elemente und Funkionen zu Zeichenketten (Texten).
Die Klasse string
enthält zum Beispiel die feste Zeichenkette ascii_uppercase
:
import string print(string.ascii_uppercase) >>> ABCDEFGHIJKLMNOPQRSTUVWXYZ
Die Funktion find()
gibt den Index (= die Position) eines bestimmten Buchstabens innerhalb einer Zeichenkette zurück. Wenn sie den gesuchten Buchstaben nicht findet, gibt sie den Wert -1
zurück.
import string print(string.ascii_uppercase) print(string.ascii_uppercase.find(‘C’)) >>> ABCDEFGHIJKLMNOPQRSTUVWXYZ >>> 2
Einen einzelnen Buchstaben können wir nun wie folgt „verschlüsseln“, also um x Stellen im Alphabet verschieben:
import string key = 5 # Um so viel wird verschoben letter = "A" print(letter) index = string.ascii_uppercase.find(letter) # 1. index = index + key # 2. letter = string.ascii_uppercase[index] # 3. print(letter) >>>A >>>F
Um nun eine Zeichenkette (ein Wort oder einen Text) zu verschlüsseln, führen wir die Befehle aus Schritt 3 für jeden Buchstaben der Zeichenkette aus. Dazu verwenden wir eine for-Schleife:
import string key = 5 # Um so viel wird verschoben plainText = “Veni vidi vici” cipherText = “” for letter in plainText.upper(): # für jeden Buchstaben in plainText... index = string.ascii_uppercase.find(letter) index = (index + key) % 26 letter = string.ascii_uppercase[index] cipherText = cipherText + letter print(cipherText) >>> AJSNEANINEANHN
Beachte Folgendes:
uppper()
macht aus jedem Buchstaben in plainText
einen Grossbuchstaben. Dadurch enthält die Variable letter
immer einen Grossbuchstaben – egal, ob der Buchstabe in plainText
gross oder klein war. Das ist wichtig, denn in der Zeichenkette ascii_uppercase
befinden sich nur Grossbuchstaben und die Funktion find()
würde darin nichts finden, wenn letter
einen Kleinbuchstaben enthielte.index
nicht grösser als 25 wird, wird die Addition index + key mit dem Modulo-Operator ergänzt: x modulo 26 (x % 26) gibt den Rest der Division x / 26 zurück: Für alle Werte grösser 26 gibt diese Operation also an, um wieviel grösser der Wert ist. Für index = 22 (Buchstabe 'W') und key = 5 ergäbe sich der Rest 1. Der neue Buchstabe wäre dann 'B' ('A' ist an Position 0).Zeichenkette
cipherText hinzugefügt.
Das Programm in Schritt 4 gibt ein Chiffrat ohne Leerschläge aus: Anstelle eines Leerschlags wird jeweils ein 'E' ausgegeben. Das macht Sinn: Wenn find()
ein Zeichen nicht findet, gibt es den Wert -1 zurück. -1 + 5 (Verschiebungswert) ergibt 4 – das ist die Position des Buchstabens E.
caesar(plainText, key)
:
Eine zufällige monoalphabetische Substitution ist weniger leicht zu knacken als beispielsweise eine Substituion gemäss der Caesar-Methode. Hier wird für jeden Buchstaben eine andere (wenn möglich zufällige) Verschiebung festgelegt. So wird jedem Buchstaben ein anderer zugewiesen. Etwa so:
Wieder entsteht zwar nur ein Geheimalphabet, dieses zu knacken ist aber schwieriger als bei der Caesar-Methode, denn hier gibt es weit mehr mögliche Kombinationen:
“Der erste Buchstabe „A“ kann an eine von 26 möglichen Alphabetpositionen platziert werden. Für den zweiten Buchstaben „B“ gibt es dann noch 25 mögliche Plätze zur Auswahl, für den dritten 24, und so weiter. Insgesamt berechnen sich so 26·25·24·23···4·3·2·1 […] Möglichkeiten zur Verwürfelung des Alphabets. Das sind ungefähr 4·1026 Fälle und entspricht etwa 88 bit.” (wikipedia.org/wiki/Monoalphabetische_Substitution)
Ist die zufällige monoalphabetische Substitution damit sicher? Nein, denn dank der Häufigkeitsanalyse ist auch ein Geheimtext, der nach dieser Methode verschlüsselt wurde, leicht zu knacken:
Die Häufigkeitsanalsye macht sich zu nutzen, dass die Buchstaben in einer Sprache in einer bestimmten Häufigkeit vorkommen, für einen Text in deutscher Sprache ist die Häufigkeit der einzelnen Buchstaben wie folgt:
Um nun einen Geheimtext zu entschlüsseln, könntest du wie folgt vorgehen:
Die Häufigkeiten der Geheimtext-Buchstaben stimmt nicht immer überein mit der Standard-Häufigkeit des entsprechenden Klartext-Buchstabens. Je kürzer der Text, desto eher kann sie abweichen. Klar: Im Text „Anna“ zum Beispiel kommt das 'E' überhaupt nicht vor und hat damit die Häufigkeit 0.
Du kannst diese Entschlüsselungsmethode hier ausprobieren:
Sample Message (easy)
für die Caesar-Substitution und Sample Message (hard)
für die zufällige monoalphabetishe Substitution. Bei letzterer kannst du die Buchstaben erst nach Häufigkeit ordnen und dann einzeln herumschieben.
Die Vigenère-Chiffre funktioniert ähnlich wie die Caesar-Verschlüsselung; es wird aber nicht jeder Buchstabe um eine feste Anzahl Stellen verschoben. Der Verschiebungswert ändert sich fortlaufend, abhängig von einem Schlüsselwort. Anders als bei der monoalphabetischen Subsitution wird hier also nicht jedem Klartext-Buchstaben ein Geheimtext-Buchstabe zugeordnet. Stattdessen hängt der Geheimtext-Buchstabe von der Kombination aus Schlüsselwort- und Klartextbuchstabe ab. Dadurch entsteht nicht ein Geheimalphabet, sondern mehrere: Je nach Kombination, können für den Klartext-Buchstaben 'A' verschiedene Geheimtextbuchstaben entstehen.
Für den Text »Als Anna abends ass, ass Anna abends Ananas« mit dem Schlüsselwort FISCHERSFRITZ
geht die Vigenère-Verschlüsselung wie folgt:
Klartext | A | L | S | A | N | N | A | A | B | E | N | D | S | A | S | S |
Position K | 0 | 11 | 18 | 0 | 13 | 13 | 0 | 0 | 1 | 4 | 13 | 3 | 18 | 0 | 18 | 18 |
Schlüsselwort | F | I | S | C | H | E | R | S | F | R | I | T | Z | F | I | S |
Position S | 5 | 8 | 18 | 2 | 7 | 4 | 17 | 18 | 5 | 17 | 8 | 19 | 25 | 5 | 8 | 18 |
Geheimtext | F | T | K | C | U | R | R | S | G | V | V | W | R | F | A | K |
Position G | 5 | 19 | 10 | 2 | 20 | 17 | 17 | 18 | 6 | 21 | 21 | 22 | 17 | 5 | 0 | 10 |
Beachte:
G = (K+S) % 26
)
Ist die Vigenère-Verschlüsselung sicher? Das hängt von der Länge und Zufälligkeit des Schlüsselwortes ab: kurze, einfach zu merkende Schlüsselwörter wie etwa “geheim” sind relativ unsicher; längere und zufälligere wie “wpfuVNaubLdshkYs” sind sicherer.
Als nicht-knackbar gilt das one-time-pad (OTP), eine Einmalverschlüsselung, bei der das Schlüsselwort mindestens so lange wie der Klartext selbst und die eben nur ein einziges mal verwendet wird.
Auch das Vigenère-Verfahren (mit wiederholt verwendeten Schlüsselwörtern) gilt angesichts heutiger Entschlüsselungsmethoden als unsicher.
Die Funktion vigenere(message, key_word)
soll wie folgt funktionieren:
caesar(plainText, key)
und füge sie in die neue Datei ein.
Schreibe die Funktion vigenere(message, key_word)
. Beachte die Überlegungen aus Aufgabe 3 und wenn nötig die Tipps.
Erweitere die Funktion um ein drittes Argument namens encrypt
: vigenere(message, key_word, encrypt)
.
encrypt
= 1 ist, soll die Funktion verschlüsseln, wen encrypt
= -1 ist, soll sie entschlüsseln.encrypt
einfach als Faktor verwendet werden, dann bräuchte es keine if-Abfrage.Teste deine (erweiterte) Vigenere-Funktion mit folgendem Code:
keyWord = "FischersFritz" cipherText = vigenere("Als Anna abends ass, ass Anna abends Ananas", keyWord, 1) print(cipherText) print(vigenere(cipherText, keyWord, -1))
Prüfe, ob dein Programm Folgendes ausgibt. Falls nicht, musst du noch Änderungen vornehmen.
>>> FTK CURR SGVVWR FAK, CZW RFSR IUDSLK CUEESX >>> ALS ANNA ABENDS ASS, ASS ANNA ABENDS ANANAS
Stellt euch gegenseitig verschlüsselte Rechenaufgaben in Textform, zum Beispiel „HUNDERTACHTUNDVIERZIG DURCH VIER“:
Dieser Abschnitt behandelt hauptsächlich die XOR-Verschlüsselung. Sie ist eines der einfachsten Beispiele moderner symmetrischer Verschlüsselungs-Verfahren. Moderne Verfahren verschlüsseln nicht gedruckte oder handgeschriebene Texte, sondern digitale Daten (Texte, Bilder, Audio-Dateien, Videos, Code). Eine Verschlüsselung über die Alphabet-Nummerierung macht wenig Sinn, denn:
100’0001
1110’1101 0001’1100 0010’0100
Also kann die moderne Verschlüsselung bei den Einsen und Nullen ansetzen.
Der American Standard Code for Information Interchange wurde bereits 1963 veröffentlicht und dient, wie es der Name sagt, dem Austausch von Informationen. Die Idee ist klar: Wenn man schon in der Lage ist, Einsen und Nullen über Kupferleitungen hin- und her zu schicken, wäre es noch praktisch, auf diese Weise auch Information, also Text, auszutauschen. Dazu muss man sich einigen, welche Binährzahl welchem Text-Zeichen entspricht. Genau das macht der ASCII-Code:
In obenstehender Tabelle kann für jedes Zeichen die entsprechende Binärzahl (von links nach rechts) gelesen werden, indem man erst die Zahlenfolge der Spalte, dann jene der Zeile liest:
100’0001
(Dezimal: 65)101’1010
(Dezimal: 90)Der alte ASCII-Code weist nur 7 Bit auf, kann also maximal 128 Zeichen speichern. Er wurde mittlerweile vom UniCode-Standard abgelöst, damit auch Schriftzeichen anderer Sprachen Platz haben. Die Gross- und Kleinbuchstaben von A…Z haben auch im UniCode dieselben Nummern wie im ASCII-Code. So gesehen ist der ASCII-Code immer noch gültig.
XOR steht für Exclusive OR, also „Exklusives ODER“, und ist eine logische Verknüpfung. Logische Verknüpfungen finden wir auch in unserer Sprache:
Wenn wir 0
als falsch und 1
als wahr ansehen, ergeben sich für ODER und für XOR folgende Wahrheitstabellen:
Beachte für die XOR-Wahrheitstabelle:
A
und B
gleich sind, ist das Resultat
0, wenn sie verschieden sind, ist das Resultat 1Resultat
XOR B
ergibt A
!
Wenn wir XOR als logischen Operator verwenden, können wir damit Kombinationen von Nullen und Einsen verschlüsseln. Wir können sagen: Geheimtext = Klartext XOR Schlüsselwort. Folgend wird der erste Buchstabe des Klartexts mit dem ersten Buchstaben des Schlüsselworts „verXORt“ (=mit dem XOR-Operator verrechnet):
100’0001
(= 65),101’0111
(= 87):
Die XOR-Operation ergibt 001’0110
(= 22). Dieser Zahl entspricht im ASCII-Code kein Buchstabe, sondern ein Steuerzeichen. Wenn es als Text angezeigt wird, sieht es vielleicht so aus: ‘<‘.
Die Verschlüsselung geht auch rückwärts: ‘<‘ XOR ‘W’ = ‘A’
Mit dieser Verschlüsselungsmethode können alle Binärzahlen und damit Daten in digitaler Form (Text, Videos, Fotos, etc.) verschlüsselt werden!
Gegeben ist folgender Geheimtext: 7 42 32 60
. Die ASCII-Codes sind hier als Dezimalzahlen angegeben. Das Schlüsselwort heisst WOLF
.
Schreibe eine Funktion crypt_xor(message_in, key_word)
:
Du kannst von der Vigenère-Funktion ausgehen, welche ebenfalls ein Schlüsselwort benutzt, das stets wiederholt wird. Überlege erst, welche Code-Zeilen du von der Vigenère-Funktion, die ja das Alphabet benutzt, nicht mehr brauchst. Beachte Folgendes:
ord()
gibt den ASCII-Code eines Zeichens zurück: ord('A')
gibt 65
zurück.chr()
gibt das Zeichen eines ASCII-Codes zurück: chr(65)
gibt 'A'
zurück.^
(auf deiner Tastatur rechts neben dem Fragezeichen):
Teste deine Funktion mit folgendem Code:
key = "WOLF" cipher = crypt_xor("Nur ein garstiges Aschenputtel ist noch da. Das sitzt unten in der Asche, dem kann der Pantoffel nicht passen!", key) print(cipher) print(crypt_xor(cipher, key))
Prüfe, ob dein Programm funktioniert: Die erste Ausgabezeile kann von der untenstehenden abweichen, die zweite aber sollte den Klartext 1:1 wiedergeben.
>>>:>f2&"f0.>5#&+#$o >>> 54')(':822#l/$;l(8,$f3.bf.?f$&8<#o9(#*"f>!l"2=l$,$#{o(#:o''9!l"2=l6!8)1))*w!%%?;l66<?#9n >>> Nur ein garstiges Aschenputtel ist noch da. Das sitzt unten in der Asche, dem kann der Pantoffel nicht passen!