{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Kryptographie" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Geheimnisse werden bevorzugt verschlüsselt übermittelt.\n", "Dieses Kapitel zeigt einige Varianten, \n", "wie einfache Verschlüsselungsmethoden implementiert werden können." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Caesarkodierung\n", "\n", "Die [Caesarkodierung](http://de.wikipedia.org/wiki/Caesar-Verschl%C3%BCsselung) geht auf einfaches Vertauschen von Buchstaben zurück." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [], "source": [ "start = ord(\"A\")\n", "end = ord(\"Z\")\n", "length = end - start" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from string import ascii_uppercase\n", "\n", "def create_code(n):\n", " def encoder(word):\n", " cipher = []\n", " for char in word:\n", " if char in ascii_uppercase:\n", " enc = chr((ord(char) - start + n) % length + start)\n", " cipher.append(enc)\n", " else:\n", " cipher.append(char)\n", " return ''.join(cipher)\n", " return encoder" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'OLE TEF RPSPTX'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "code1 = create_code(11)\n", "cc = code1(\"DAS IST GEHEIM\")\n", "cc" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'DAS IST GEHEIM'" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "code2 = create_code(-11)\n", "code2(cc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das Problem ist, die Häufigkeit der einzelnen Buchstaben ist nicht gleich.\n", "Daher lässt sich mit einer einfachen Statistik erahnen,\n", "welcher Buchstabe wie verschlüsselt ist." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# use a counter, greate a plt.hbar plot, and set the y_axis labels to uppercase" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Enigma" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die [Enigma Verschlüsselungsmaschine](http://en.wikipedia.org/wiki/Enigma_machine) ist ähnlich einer Schreibmaschine.\n", "Buchstaben von \"A\" bis \"Z\" werden gedrückt,\n", "um variabel verdrahteten Stromkreise zu schließen.\n", "Nach jedem Tastendruck drehen die Rotoren um einen Schritt weiter.\n", "Je nach der Stellung der Rotoren (und einem fixen Steckbrett) leuchten Lämpchen von \"A\" bis \"Z\" auf.\n", "\n", "Im folgenden programmieren wir eine an die Enigma Maschine angelehnte Verschlüsselungsmethode in Python.\n", "Zur besseren Lesbarkeit inkludieren wir auch das Leerzeichen, und alle anderen Zeichen werden ohne Verschlüsselung als \".\" wiedergegeben.\n", "Das Steckbrett wird ausgelassen, es würde nur zusätzlich noch ein paar Buchstaben untereinander austauschen.\n", "\n", "Die Funktionsweise ist die folgende:\n", "Die Rotoren und der Reflektor haben intern eine zufällige Permutation gespeichert.\n", "Der initiale Buchstabenindex wird durch die Rotoren zum Permutieren geschickt,\n", "der starre Reflektor dreht den \"Stromfluss\" um,\n", "und in umgekehrter Reihenfolge die inversen Permutationsoperationen der Rotoren abzuarbeiten.\n", "\n", "Nach jedem Buchstaben springt das Zählwerk der Rotoren um eins weiter.\n", "\n", "Zur Entschlüsselung müssen die Rotoren der Enigma wieder in ihren Anfangszustand zurückgesetzt werden.\n", "\n", "Anzumerken ist außerdem, dass in der echten Version nur eine kleine Anzahl von Rotor und Reflektor Permutationen existierten. Diese Implementation hier erlaubt jegliche Art von Permutationen, eben auch solche, welche einen Kurzschluss im Stromkreis erzeugen würden.\n", "\n", "Eine wahrheitsgetreuere Implementation liefert [py-enigma](http://py-enigma.readthedocs.org/en/latest/)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Rotor(object):\n", " \"\"\"\n", " Der Rotor permutiert den eingegebenen Buchstaben entsprechend seiner Rotationsstellung.\n", " Nach einer vollen Rotation wird an den nächsten Rotor das Signal zum Vorrücken weitergegeben.\n", " \"\"\"\n", " def __init__(self, length):\n", " self.length = length\n", " self.permutation = list(range(length))\n", " from random import shuffle\n", " shuffle(self.permutation)\n", " self.position = 0\n", " self.next_rotor = None\n", "\n", " def rotate(self):\n", " self.position = (self.position + 1) % self.length\n", " if self.position == 0:\n", " self.next_rotor.rotate()\n", " \n", " def reset(self):\n", " self.position = 0\n", "\n", " def forward(self, c):\n", " idx = (self.position + c) % self.length\n", " return self.permutation[idx]\n", " \n", " def inverse(self, c):\n", " idx = self.permutation.index(c)\n", " return (idx - self.position) % self.length" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Reflector(Rotor):\n", " \"\"\"\n", " Am Ende der Reihe von Rotoren, gibt es einen Reflector (Unterklasse von Rotor).\n", " Er schickt das Signal an eine permutierte Stelle zurück für die inverse Operation.\n", " \n", " Es gab Varianten mit einem rotierendne Reflektor, hier ist er starr.\n", " \"\"\"\n", " def __init__(self, l):\n", " super(Reflector, self).__init__(l)\n", " \n", " def rotate(self):\n", " pass\n", " \n", " def reset(self):\n", " pass\n", "\n", " def reflect(self, c, encrypt):\n", " if encrypt:\n", " return self.permutation[c]\n", " else:\n", " return self.permutation.index(c)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Enigma(object):\n", " \"\"\"\n", " Diese Enigma Hauptklasse instanziert die Rotoren und den Reflektor.\n", " Die Methode `run` simuliert den Stromfluss durch die Rotoren und den Reflektor.\n", " \"\"\"\n", " def __init__(self):\n", " import string\n", " self.letters = list(string.ascii_uppercase + \" \")\n", " l = len(self.letters)\n", " \n", " self.rotors = rotors = [Rotor(l), Rotor(l), Rotor(l), Rotor(l)]\n", " self.reflector = Reflector(l)\n", " \n", " for i in range(len(rotors) - 1):\n", " rotors[i].next_rotor = rotors[i+1]\n", " \n", " def reset(self):\n", " for r in self.rotors:\n", " r.reset()\n", " self.reflector.reset()\n", " \n", " def run(self, char, encrypt = True):\n", " char = char.upper()\n", " if char not in self.letters:\n", " return \".\"\n", " c = self.letters.index(char)\n", " for r in self.rotors:\n", " c = r.forward(c)\n", " c = self.reflector.reflect(c, encrypt)\n", " for r in self.rotors[::-1]:\n", " c = r.inverse(c)\n", " self.rotors[0].rotate()\n", " return self.letters[c]" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import random\n", "seed = 1938 # damit die Zufallsresultate immer gleich sind.\n", "random.seed(seed)\n", "e = Enigma()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "VRZMRDDHC SZKROKK DKTFCRCZRETITZEYEEKXEKXFRRAXLVHMMVYJCUCLJIUWXPNGJZLIQBURNAJBJRVZLOCRRKEFXKUDNZY VJTGZ CPSBZKOTJLRRYLFTVSPJPVWX OGGKQMPR T MYUFUQLXSBBNCEDNDPZAXQMZRSNVQL\n" ] } ], "source": [ "from __future__ import print_function\n", "plain = \"\"\"\\\n", "DIES IST EIN GEHEIMER TEXT DEN DIE PROGRAMMIERSPRACHE \\\n", "PYTHON IN EINER AN DIE MECHANIK DER ENIGMA CHIFFRIERMASCHINE \\\n", "ANGELEHNTEN WEISE VERSCHUESSELN UND ENTSCHLUESSLEN KANN\\\n", "\"\"\"\n", "e.reset()\n", "cipher = \"\".join(e.run(char) for char in plain)\n", "print(cipher)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "DIES IST EIN GEHEIMER TEXT DEN DIE PROGRAMMIERSPRACHE PYTHON IN EINER AN DIE MECHANIK DER ENIGMA CHIFFRIERMASCHINE ANGELEHNTEN WEISE VERSCHUESSELN UND ENTSCHLUESSLEN KANN" ] } ], "source": [ "e.reset()\n", "for char in cipher:\n", " print(e.run(char, encrypt=False), end=\"\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Anaconda (Python 3)", "language": "python", "name": "anaconda3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }