Umgang mit zweidimensionalen Feldern lernen – am Beispiel der Vigenére-Verschlüsselung

In diesem Beitrag möchte ich den Umgang mit zweidimensionalen Feldern in Python an einem sehr netten Beispiel veranschaulichen. Gleich vorweg, es gibt eigentlich keine mehrdimensionalen Felder in Python, sondern nur Listen, die als Elemente Listen enthalten. Und was bedeutet überhaupt zweidimensioal?

Ganz einfach, stellt Euch bitte kurz ein Brett vor, das aus horizontalen und vertikalen Reihen mit einer bestimmten und immer gleichen Anzahl an Feldern pro Reihe besteht. Bei einem Schachbrett gibt es bekanntlich acht Zeilen mit jeweils 8 Feldern. Also ein 8×8-Feld mit 64 Feldern. Bei einem Schiffe versenken-Spiel sind es 10 Reihen mit jeweils 10 Feldern. Also ein 10×10-Feld. Möchte man ein solches Brett mit seinen Feldern in einer Programmiersprache abbilden, benötigt man ein zweidimensionales Feld. Folglich gibt es auch zwei Indices. Für jede „Dimension“ ein Index.

Die allgemeine Schreibweise Feld[0,0] spricht das Feld in der linken, oberen Ecke an, die Schreibweise Feld[3,3] das Feld in der Mitte usw. Warum 0 und warum 3 und nicht 4? Ganz einfach, weil bei fast allen Programmiersprachen die Nummerierung bei 0 beginnt und nicht bei 1.

Wer sich im Internet ein wenig zum Thema „Python und Arrays“ umsieht findet schnell Beispiele, in denen Arrays verwendet werden. Kann Python daher doch Array?Nein und Ja. Nein, weil es Arrays offiziell nicht gibt. Ja, weil über Erweiterungen wie NumPy Arrays und Matrizen als eigene Datentypen hinzukommen. Im Folgenden geht es aber nur Listen, die wie Felder behandelt werden können.

Da das Beispielprogramm etwas umfangreicher ist und nicht jeder, der die Seite liest, sich bereits mit Feldern bei Python auskennt, zuerst ein Beispiel zur „Einstimmung“. Ich verwende aber mit Absicht keine Erweiterung wie NumPy, da es nur um die reine Python-Programmierung gehen soll.

Der erste Befehl legt eine leere Liste an:

f = []

Die Liste ist aber noch leer. Soll sie z.B. bereits zehn Nullen enthalten, ist List Comprehension praktisch, denn man spart sich eine for-Schleife mit Zuweisung:

f = [0 for i in range(0,10)]

Anschließend erhalten die ersten zwei oder drei Reihen ebenfalls eine Liste als Wert:

f[0] = [i for i in range(1,11)]
f[1] = [i for i in range(1,11)]
f[2] = [i for i in range(1,11)]

Natürlich hätte ich das Feld auch mit einem einzigen Befehl anlegen und befüllen können, aber so ist es etwas anschaulicher (dieser Befehl kommt in dem Beispielprogramm vor).

Jetzt wäre die Frage, wie ein Element, also eine Zahl, in der Listen-Liste angesprochen wird. Eigentlich sehr naheliegend durch folgende Schreibweise:

f[0][1]

Die bei anderen Programmiersprachen übliche Schreibweise f[0,1] geht bei Python nicht, da dies die Slicing-Schreibweise ist.

Jetzt zu dem eigentlichen Beispiel. Es veranschaulicht die Vigenére-Chiffre, die ich vor kurzem im Rahmen meines OMI-Studiums im Modul „Grundlagen der Informationssicherheit“ (GIS) kennengelernt habe.

Vigenére-Chiffre ermöglichen eine einfache“ Verschlüsselung“ Worten mit Hilfe eines Schlüssels, der wiederum nichts anderes als ein beliebiges Wort ist. Die Grundlage ist eine Tabelle mit z.B. 26 Spalten und 26 Zeilen. Warum 26? Damit alle Buchstaben des Alphabets in einer Zeile Platz haben. Die Tabelle ist so aufgebaut, dass jede Zeile die Buchstaben von A bis Z enthält, ab der zweiten Zeile aber immer um einen Buchstaben versetzt. Die erste Zeile beginnt mit A,B,C,D, die zweite mit B,C,D,E, die dritte mit C,D,E,F usw. Nach dem Z geht es in einer Zeile mit A wieder weiter.

Die Verschlüsselung besteht darin, dass das zu verschlüsselnde Wort Buchstabe für Buchstabe durchgegangen wird. Soll z.B. das Wort SOMMER verschlüsselt werden, gehen wir die Buchstaben S, O, M, M, E und R durch. Für jeden Buchstaben wird der Buchstabe mit jedem in Bezug auf die Position des Buchstabens korrespondierenden Buchstaben aus dem Schlüssel kombiniert. Heißt der Schlüssel z.B. GEHEIM, passt das S zum G, das O zum E, das M zum H usw. Der zweite Buchstabe legt die Zeile fest. Aus der Kombination Spalte und Zeile ergibt sich jeweils ein Buchstabe, der zum Chiffre hinzugefügt wird. Der Chiffre ist die verschlüsselte Form des Wortes.

Und was ist, wenn der Schlüssel kürzer ist als das zu verschlüsselnde Wort? Das ist natürlich kein Problem, wenn dann wird wieder der erste Buchstabe aus dem Schlüssel verwendet usw.

Wer das Ganze trotz meiner Bemühungen immer noch nicht verstanden hat, soll es bitte noch einmal bei Wikipedia nachlesen:

https://de.wikipedia.org/wiki/Vigen%C3%A8re-Chiffre

Dort wird alles natürlich viel komplizierter erklärt;)

Neben einer ausführlichen (und natürlich sehr guten) Erklärung findet ihr dort auch ein Beispiel für die von mir wortreich beschriebene Chiffre-Tabelle.

Doch nun zur Umsetzung in einem Python-Programm. Ich kann jedem nur empfehlen, die Aufgabe erst einmal selber zu lösen, da sie doch einiges an „Grundverständnis“ der Python-Programmierung abverlangt. Nicht, weil die Programmierung besonders kompliziert oder anspruchsvoll wäre, sondern weil es auf ein paar „Randbedingungen“ ankommt, die beim Programmieren immer das sprichwörtliche Salz in der Suppe sind.

Wenn man ein Wort erfolgreich verschlüsselt hat, möchte man es natürlich auch wieder lesbar machen. Das soll zunächst eine Übung sein, die jeder bitte alleine lösen soll, da die Lösung a) nicht schwer ist und ich b) niemanden das Erfolgserlebnis vorenthalten möchte. Probiert es einmal aus, es lohnt sich!

Das Beispiel findet ihr natürlich in meinem GitHub-Repo unter https://github.com/pemo11/pyhub. Am besten alle Beispiele (allzu viele sind es im Moment aber noch nicht) per git clone oder gleich in Visual Studio Code herunterladen (zur Not auch als Zip-Datei, wenn es mit den Git Tools für Windows wider Erwarten nicht funktionieren sollte).

# Vigenére Chiffre
# Umsetzung am 9.06.2020
# Autor: Peter Monadjemi
 
# Schritt 1: 26x26 Feld mit den jeweils pro Spalte um einen Buchstaben versetzen Buchstaben von A bis Z

# Thereotisch ließe sich das Fels auch gleich per List Comprehension passend füllen
vigFeld = [[0 for i in range(0,26)] for j in range(0,26)]

offset = 0

# Ergebnis stimmt, kann aber eventuell vereinfacht werden
for i in range(0,26):
    for j in range(0,26):
        c = j + offset + 65
        c = c - 26 if c > 90 else c
        vigFeld[i][j] = chr(c)
    offset += 1
 
for i in range(0,26):
    print(vigFeld[i])

# Das Wort "SEMESTER" soll mit dem Schlüssel SICHER verschüsselt werden
wort = "SEMESTER"
schluessel = "SICHER"
geheim = ""

k = 0
for c in wort:
    i = ord(c) - 65
    j = ord(schluessel[k]) - 65
    k = k + 1 if k < len(schluessel) - 1 else 0
    geheim += vigFeld[i][j]

# Stimmt - aus SEMESTER wird KMOLWKWZ
print(geheim)

# Wie muss eine Entschlüsselungsfunktion aussehen?

Schreibe einen Kommentar

Pflichtfelder sind mit * markiert.


Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.