{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Enigma machine\n", "Specification from [Codes and Ciphers](http://www.codesandciphers.org.uk/enigma/rotorspec.htm) page.\n", "\n", "Example Enigma machines from [Louise Dale](http://enigma.louisedade.co.uk/enigma.html) (full simulation) and [EnigmaCo](http://enigmaco.de/enigma/enigma.html) (good animation of the wheels, but no ring settings).\n", "\n", "There's also the nice Enigma simulator for Android by [Franklin Heath](https://franklinheath.co.uk/2012/02/04/our-first-app-published-enigma-simulator/), available on the [Google Play store](https://play.google.com/store/apps/details?id=uk.co.franklinheath.enigmasim&hl=en_GB)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import string\n", "import collections\n", "\n", "cat = ''.join\n", "\n", "def clean(text): return cat(l.lower() for l in text if l in string.ascii_letters)\n", "\n", "def pos(letter): \n", " if letter in string.ascii_lowercase:\n", " return ord(letter) - ord('a')\n", " elif letter in string.ascii_uppercase:\n", " return ord(letter) - ord('A')\n", " else:\n", " return ''\n", " \n", "def unpos(number): return chr(number % 26 + ord('a'))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "wheel_i_spec = 'ekmflgdqvzntowyhxuspaibrcj'\n", "wheel_ii_spec = 'ajdksiruxblhwtmcqgznpyfvoe'\n", "wheel_iii_spec = 'bdfhjlcprtxvznyeiwgakmusqo'\n", "wheel_iv_spec = 'esovpzjayquirhxlnftgkdcmwb'\n", "wheel_v_spec = 'vzbrgityupsdnhlxawmjqofeck'\n", "wheel_vi_spec = 'jpgvoumfyqbenhzrdkasxlictw'\n", "wheel_vii_spec = 'nzjhgrcxmyswboufaivlpekqdt'\n", "wheel_viii_spec = 'fkqhtlxocbjspdzramewniuygv'\n", "beta_wheel_spec = 'leyjvcnixwpbqmdrtakzgfuhos'\n", "gamma_wheel_spec = 'fsokanuerhmbtiycwlqpzxvgjd'\n", "\n", "wheel_i_pegs = ['q']\n", "wheel_ii_pegs = ['e']\n", "wheel_iii_pegs = ['v']\n", "wheel_iv_pegs = ['j']\n", "wheel_v_pegs = ['z']\n", "wheel_vi_pegs = ['z', 'm']\n", "wheel_vii_pegs = ['z', 'm']\n", "wheel_viii_pegs = ['z', 'm']\n", "\n", "reflector_b_spec = 'ay br cu dh eq fs gl ip jx kn mo tz vw'\n", "reflector_c_spec = 'af bv cp dj ei go hy kr lz mx nw tq su'" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class LetterTransformer(object):\n", " def __init__(self, specification, raw_transform=False):\n", " if raw_transform:\n", " transform = specification\n", " else:\n", " transform = self.parse_specification(specification)\n", " self.validate_transform(transform)\n", " self.make_transform_map(transform)\n", " \n", " def parse_specification(self, specification):\n", " return list(zip(string.ascii_lowercase, clean(specification)))\n", " # return specification\n", " \n", " def validate_transform(self, transform):\n", " \"\"\"A set of pairs, of from-to\"\"\"\n", " if len(transform) != 26:\n", " raise ValueError(\"Transform specification has {} pairs, requires 26\".\n", " format(len(transform)))\n", " for p in transform:\n", " if len(p) != 2:\n", " raise ValueError(\"Not all mappings in transform \"\n", " \"have two elements\")\n", " if len(set([p[0] for p in transform])) != 26:\n", " raise ValueError(\"Transform specification must list 26 origin letters\") \n", " if len(set([p[1] for p in transform])) != 26:\n", " raise ValueError(\"Transform specification must list 26 destination letters\") \n", "\n", " def make_empty_transform(self):\n", " self.forward_map = [0] * 26\n", " self.backward_map = [0] * 26\n", " \n", " def make_transform_map(self, transform):\n", " self.make_empty_transform()\n", " for p in transform:\n", " self.forward_map[pos(p[0])] = pos(p[1])\n", " self.backward_map[pos(p[1])] = pos(p[0])\n", " return self.forward_map, self.backward_map\n", " \n", " def forward(self, letter):\n", " if letter in string.ascii_lowercase:\n", " return unpos(self.forward_map[pos(letter)])\n", " else:\n", " return ''\n", " \n", " def backward(self, letter):\n", " if letter in string.ascii_lowercase:\n", " return unpos(self.backward_map[pos(letter)])\n", " else:\n", " return ''" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('z', 'a'),\n", " ('a', 'b'),\n", " ('b', 'c'),\n", " ('c', 'd'),\n", " ('d', 'e'),\n", " ('e', 'f'),\n", " ('f', 'g'),\n", " ('g', 'h'),\n", " ('h', 'i'),\n", " ('i', 'j'),\n", " ('j', 'k'),\n", " ('k', 'l'),\n", " ('l', 'm'),\n", " ('m', 'n'),\n", " ('n', 'o'),\n", " ('o', 'p'),\n", " ('p', 'q'),\n", " ('q', 'r'),\n", " ('r', 's'),\n", " ('s', 't'),\n", " ('t', 'u'),\n", " ('u', 'v'),\n", " ('v', 'w'),\n", " ('w', 'x'),\n", " ('x', 'y'),\n", " ('y', 'z')]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tmap = [('z', 'a')] + [(l, string.ascii_lowercase[i+1]) for i, l in enumerate(string.ascii_lowercase[:-1])]\n", "tmap" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'zyxwcabdefghijklmnopqrstuv'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true, "scrolled": true }, "outputs": [], "source": [ "tmap2 = list(zip(string.ascii_lowercase, cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "([1,\n", " 2,\n", " 3,\n", " 4,\n", " 5,\n", " 6,\n", " 7,\n", " 8,\n", " 9,\n", " 10,\n", " 11,\n", " 12,\n", " 13,\n", " 14,\n", " 15,\n", " 16,\n", " 17,\n", " 18,\n", " 19,\n", " 20,\n", " 21,\n", " 22,\n", " 23,\n", " 24,\n", " 25,\n", " 0],\n", " [25,\n", " 0,\n", " 1,\n", " 2,\n", " 3,\n", " 4,\n", " 5,\n", " 6,\n", " 7,\n", " 8,\n", " 9,\n", " 10,\n", " 11,\n", " 12,\n", " 13,\n", " 14,\n", " 15,\n", " 16,\n", " 17,\n", " 18,\n", " 19,\n", " 20,\n", " 21,\n", " 22,\n", " 23,\n", " 24])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lt = LetterTransformer(tmap, raw_transform = True)\n", "assert(lt.forward_map == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0])\n", "assert(lt.backward_map == [25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])\n", "lt.forward_map, lt.backward_map" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "([25,\n", " 24,\n", " 23,\n", " 22,\n", " 2,\n", " 0,\n", " 1,\n", " 3,\n", " 4,\n", " 5,\n", " 6,\n", " 7,\n", " 8,\n", " 9,\n", " 10,\n", " 11,\n", " 12,\n", " 13,\n", " 14,\n", " 15,\n", " 16,\n", " 17,\n", " 18,\n", " 19,\n", " 20,\n", " 21],\n", " [5,\n", " 6,\n", " 4,\n", " 7,\n", " 8,\n", " 9,\n", " 10,\n", " 11,\n", " 12,\n", " 13,\n", " 14,\n", " 15,\n", " 16,\n", " 17,\n", " 18,\n", " 19,\n", " 20,\n", " 21,\n", " 22,\n", " 23,\n", " 24,\n", " 25,\n", " 3,\n", " 2,\n", " 1,\n", " 0])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))\n", "assert(lt.forward_map == [25, 24, 23, 22, 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])\n", "assert(lt.backward_map == [5, 6, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 3, 2, 1, 0])\n", "assert(cat(lt.forward(l) for l in string.ascii_lowercase) == 'zyxwcabdefghijklmnopqrstuv')\n", "assert(cat(lt.backward(l) for l in string.ascii_lowercase) == 'fgehijklmnopqrstuvwxyzdcba')\n", "lt.forward_map, lt.backward_map" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'zyxwcabdefghijklmnopqrstuv'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(lt.forward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'fgehijklmnopqrstuvwxyzdcba'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(lt.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Plugboard(LetterTransformer):\n", " def parse_specification(self, specification):\n", " return [tuple(clean(p)) for p in specification.split()]\n", " \n", " def validate_transform(self, transform):\n", " \"\"\"A set of pairs, of from-to\"\"\"\n", " for p in transform:\n", " if len(p) != 2:\n", " raise ValueError(\"Not all mappings in transform\"\n", " \"have two elements\")\n", " \n", " def make_empty_transform(self):\n", " self.forward_map = list(range(26))\n", " self.backward_map = list(range(26))\n", " \n", " def make_transform_map(self, transform):\n", " expanded_transform = transform + [tuple(reversed(p)) for p in transform]\n", " return super(Plugboard, self).make_transform_map(expanded_transform)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pb = Plugboard([('a', 'z'), ('b', 'y')], raw_transform=True)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'zycdefghijklmnopqrstuvwxba'" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(pb.forward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'zycdefghijklmnopqrstuvwxba'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(pb.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pb = Plugboard('az by')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('zycdefghijklmnopqrstuvwxba', 'zycdefghijklmnopqrstuvwxba')" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(pb.forward(l) for l in string.ascii_lowercase), cat(pb.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('ugcdypblnzkhmisfrqoxavwtej', 'ugcdypblnzkhmisfrqoxavwtej')" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper())\n", "assert(pb.forward_map == pb.backward_map)\n", "assert(pb.forward_map == [20, 6, 2, 3, 24, 15, 1, 11, 13, 25, 10, 7, 12, 8, 18, 5, 17, 16, 14, 23, 0, 21, 22, 19, 4, 9])\n", "assert(cat(pb.forward(l) for l in string.ascii_lowercase) == 'ugcdypblnzkhmisfrqoxavwtej')\n", "assert(cat(pb.backward(l) for l in string.ascii_lowercase) == 'ugcdypblnzkhmisfrqoxavwtej')\n", "cat(pb.forward(l) for l in string.ascii_lowercase), cat(pb.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Reflector(Plugboard):\n", " def validate_transform(self, transform):\n", " if len(transform) != 13:\n", " raise ValueError(\"Reflector specification has {} pairs, requires 13\".\n", " format(len(transform)))\n", " if len(set([p[0] for p in transform] + \n", " [p[1] for p in transform])) != 26:\n", " raise ValueError(\"Reflector specification does not contain 26 letters\")\n", " try:\n", " super(Reflector, self).validate_transform(transform)\n", " except ValueError as v:\n", " raise ValueError(\"Not all mappings in reflector have two elements\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('a', 'y'),\n", " ('b', 'r'),\n", " ('c', 'u'),\n", " ('d', 'h'),\n", " ('e', 'q'),\n", " ('f', 's'),\n", " ('g', 'l'),\n", " ('i', 'p'),\n", " ('j', 'x'),\n", " ('k', 'n'),\n", " ('m', 'o'),\n", " ('t', 'z'),\n", " ('v', 'w')]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# reflector_b_text = '(AY) (BR) (CU) (DH) (EQ) (FS) (GL) (IP) (JX) (KN) (MO) (TZ) (VW)'\n", "reflector_b_l = [tuple(clean(p)) for p in reflector_b_spec.split()]\n", "reflector_b_l" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "reflector_b = Reflector(reflector_b_spec)\n", "assert(reflector_b.forward_map == reflector_b.backward_map)\n", "assert(reflector_b.forward_map == [24, 17, 20, 7, 16, 18, 11, 3, 15, 23, 13, 6, 14, 10, 12, 8, 4, 1, 5, 25, 2, 22, 21, 9, 0, 19])\n", "assert(cat(reflector_b.forward(l) for l in string.ascii_lowercase) == 'yruhqsldpxngokmiebfzcwvjat')\n", "assert(cat(reflector_b.backward(l) for l in string.ascii_lowercase) == 'yruhqsldpxngokmiebfzcwvjat')" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'yruhqsldpxngokmiebfzcwvjat'" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(reflector_b.forward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true }, "outputs": [], "source": [ "reflector_c = Reflector(reflector_c_spec)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'fvpjiaoyedrzxwgctkuqsbnmhl'" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(reflector_c.forward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class SimpleWheel(LetterTransformer):\n", " def __init__(self, transform, position='a', raw_transform=False):\n", " super(SimpleWheel, self).__init__(transform, raw_transform)\n", " self.set_position(position)\n", " \n", " def __getattribute__(self,name):\n", " if name=='position_l':\n", " return unpos(self.position)\n", " else:\n", " return object.__getattribute__(self, name)\n", " \n", " def set_position(self, position):\n", " self.position = ord(position) - ord('a')\n", " \n", " def forward(self, letter):\n", " if letter in string.ascii_lowercase:\n", " return unpos((self.forward_map[(pos(letter) + self.position) % 26] - self.position))\n", " else:\n", " return ''\n", " \n", " def backward(self, letter):\n", " if letter in string.ascii_lowercase:\n", " return unpos((self.backward_map[(pos(letter) + self.position) % 26] - self.position))\n", " else:\n", " return ''\n", " \n", " def advance(self):\n", " self.position = (self.position + 1) % 26\n", " return self.position" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[('a', 'e'),\n", " ('b', 'k'),\n", " ('c', 'm'),\n", " ('d', 'f'),\n", " ('e', 'l'),\n", " ('f', 'g'),\n", " ('g', 'd'),\n", " ('h', 'q'),\n", " ('i', 'v'),\n", " ('j', 'z'),\n", " ('k', 'n'),\n", " ('l', 't'),\n", " ('m', 'o'),\n", " ('n', 'w'),\n", " ('o', 'y'),\n", " ('p', 'h'),\n", " ('q', 'x'),\n", " ('r', 'u'),\n", " ('s', 's'),\n", " ('t', 'p'),\n", " ('u', 'a'),\n", " ('v', 'i'),\n", " ('w', 'b'),\n", " ('x', 'r'),\n", " ('y', 'c'),\n", " ('z', 'j')]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rotor_1_transform = list(zip(string.ascii_lowercase, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))\n", "rotor_1_transform" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": true }, "outputs": [], "source": [ "rotor_1_transform = list(zip(string.ascii_lowercase, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))\n", "wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True)\n", "assert(cat(wheel_1.forward(l) for l in string.ascii_lowercase) == 'ekmflgdqvzntowyhxuspaibrcj')\n", "assert(cat(wheel_1.backward(l) for l in string.ascii_lowercase) == 'uwygadfpvzbeckmthxslrinqoj')" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('ekmflgdqvzntowyhxuspaibrcj', 'uwygadfpvzbeckmthxslrinqoj')" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(wheel_1.forward(l) for l in string.ascii_lowercase), cat(wheel_1.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'a'" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wheel_1.position_l" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": true }, "outputs": [], "source": [ "wheel_2 = SimpleWheel(wheel_ii_spec)\n", "assert(cat(wheel_2.forward(l) for l in string.ascii_lowercase) == 'ajdksiruxblhwtmcqgznpyfvoe')\n", "assert(cat(wheel_2.backward(l) for l in string.ascii_lowercase) == 'ajpczwrlfbdkotyuqgenhxmivs')" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('ajdksiruxblhwtmcqgznpyfvoe', 'ajpczwrlfbdkotyuqgenhxmivs')" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(wheel_2.forward(l) for l in string.ascii_lowercase), cat(wheel_2.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('bdfhjlcprtxvznyeiwgakmusqo', 'tagbpcsdqeufvnzhyixjwlrkom')" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wheel_3 = SimpleWheel(wheel_iii_spec)\n", "wheel_3.set_position('a')\n", "wheel_3.advance()\n", "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'cegikboqswuymxdhvfzjltrpna')\n", "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'zfaobrcpdteumygxhwivkqjnls')\n", "assert(wheel_3.position == 1)\n", "assert(wheel_3.position_l == 'b')\n", "\n", "for _ in range(24): wheel_3.advance()\n", "assert(wheel_3.position == 25)\n", "assert(wheel_3.position_l == 'z')\n", "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'pcegikmdqsuywaozfjxhblnvtr')\n", "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'nubhcqdterfvgwoaizjykxmslp')\n", "\n", "wheel_3.advance()\n", "assert(wheel_3.position == 0)\n", "assert(wheel_3.position_l == 'a')\n", "assert(cat(wheel_3.forward(l) for l in string.ascii_lowercase) == 'bdfhjlcprtxvznyeiwgakmusqo')\n", "assert(cat(wheel_3.backward(l) for l in string.ascii_lowercase) == 'tagbpcsdqeufvnzhyixjwlrkom')\n", "\n", "cat(wheel_3.forward(l) for l in string.ascii_lowercase), cat(wheel_3.backward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Wheel(SimpleWheel):\n", " def __init__(self, transform, ring_peg_letters, ring_setting=1, position='a', raw_transform=False):\n", " self.ring_peg_letters = ring_peg_letters\n", " self.ring_setting = ring_setting\n", " super(Wheel, self).__init__(transform, position=position, raw_transform=raw_transform)\n", " self.set_position(position)\n", " \n", " def __getattribute__(self,name):\n", " if name=='position_l':\n", " return unpos(self.position + self.ring_setting - 1)\n", " else:\n", " return object.__getattribute__(self, name)\n", "\n", " def set_position(self, position):\n", " self.position = (pos(position) - self.ring_setting + 1) % 26\n", " # self.position_l = position\n", " self.peg_positions = [(pos(p) - pos(position)) % 26 for p in self.ring_peg_letters]\n", " \n", " def advance(self):\n", " super(Wheel, self).advance()\n", " self.peg_positions = [(p - 1) % 26 for p in self.peg_positions]\n", " # self.position_l = unpos(self.position + self.ring_setting - 1)\n", " return self.position" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": true }, "outputs": [], "source": [ "wheel_3 = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', ring_setting=1)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, [20])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wheel_3.position, wheel_3.peg_positions" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(25, [24, 11])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wheel_6 = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', ring_setting=3)\n", "wheel_6.position, wheel_6.peg_positions" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 [23, 10]\n", "1 [22, 9]\n", "2 [21, 8]\n", "3 [20, 7]\n", "4 [19, 6]\n", "5 [18, 5]\n", "6 [17, 4]\n", "7 [16, 3]\n", "8 [15, 2]\n", "9 [14, 1]\n", "10 [13, 0]\n", "11 [12, 25]\n", "12 [11, 24]\n", "13 [10, 23]\n", "14 [9, 22]\n", "15 [8, 21]\n", "16 [7, 20]\n", "17 [6, 19]\n", "18 [5, 18]\n", "19 [4, 17]\n", "20 [3, 16]\n", "21 [2, 15]\n", "22 [1, 14]\n", "23 [0, 13]\n", "24 [25, 12]\n", "25 [24, 11]\n", "0 [23, 10]\n" ] } ], "source": [ "for _ in range(27):\n", " wheel_6.advance()\n", " print(wheel_6.position, wheel_6.peg_positions)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": true }, "outputs": [], "source": [ "wheel_3 = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', ring_setting=1)\n", "assert(wheel_3.position == 1)\n", "assert(wheel_3.peg_positions == [20])\n", "assert(wheel_3.position_l == 'b')\n", "wheel_3.advance()\n", "assert(wheel_3.position == 2)\n", "assert(wheel_3.peg_positions == [19])\n", "assert(wheel_3.position_l == 'c')" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": true }, "outputs": [], "source": [ "wheel_6 = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', ring_setting=3)\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'xkqhwpvngzrcfoiaselbtymjdu')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'ptlyrmidoxbswhnfckquzgeavj')\n", "assert(wheel_6.position == 25)\n", "assert(11 in wheel_6.peg_positions)\n", "assert(24 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'b')\n", "\n", "wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'jpgvoumfyqbenhzrdkasxlictw')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'skxqlhcnwarvgmebjptyfdzuio')\n", "assert(wheel_6.position == 0)\n", "assert(10 in wheel_6.peg_positions)\n", "assert(23 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'c')\n", "\n", "for _ in range(22): wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'mgxantkzsyqjcufirldvhoewbp')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'dymswobuplgraevzkqifntxcjh')\n", "assert(wheel_6.position == 22)\n", "assert(1 in wheel_6.peg_positions)\n", "assert(14 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'y')\n", "\n", "wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'fwzmsjyrxpibtehqkcugndvaol')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'xlrvnatokfqzduyjphemswbigc')\n", "assert(wheel_6.position == 23)\n", "assert(0 in wheel_6.peg_positions)\n", "assert(13 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'z')\n", "\n", "wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'vylrixqwohasdgpjbtfmcuznke')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'kqumzsnjepyctxiogdlrvahfbw')\n", "assert(wheel_6.position == 24)\n", "assert(25 in wheel_6.peg_positions)\n", "assert(12 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'a')\n", "\n", "wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'xkqhwpvngzrcfoiaselbtymjdu')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'ptlyrmidoxbswhnfckquzgeavj')\n", "assert(wheel_6.position == 25)\n", "assert(24 in wheel_6.peg_positions)\n", "assert(11 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'b')\n", "\n", "wheel_6.advance()\n", "assert(cat(wheel_6.forward(l) for l in string.ascii_lowercase) == 'jpgvoumfyqbenhzrdkasxlictw')\n", "assert(cat(wheel_6.backward(l) for l in string.ascii_lowercase) == 'skxqlhcnwarvgmebjptyfdzuio')\n", "assert(wheel_6.position == 0)\n", "assert(23 in wheel_6.peg_positions)\n", "assert(10 in wheel_6.peg_positions)\n", "assert(wheel_6.position_l == 'c')" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0, 'c', [23, 10])" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wheel_6.position, wheel_6.position_l, wheel_6.peg_positions" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Enigma(object):\n", " def __init__(self, reflector_spec,\n", " left_wheel_spec, left_wheel_pegs,\n", " middle_wheel_spec, middle_wheel_pegs,\n", " right_wheel_spec, right_wheel_pegs,\n", " left_ring_setting, middle_ring_setting, right_ring_setting,\n", " plugboard_setting):\n", " self.reflector = Reflector(reflector_spec)\n", " self.left_wheel = Wheel(left_wheel_spec, left_wheel_pegs, ring_setting=left_ring_setting)\n", " self.middle_wheel = Wheel(middle_wheel_spec, middle_wheel_pegs, ring_setting=middle_ring_setting)\n", " self.right_wheel = Wheel(right_wheel_spec, right_wheel_pegs, ring_setting=right_ring_setting)\n", " self.plugboard = Plugboard(plugboard_setting)\n", " \n", " def __getattribute__(self,name):\n", " if name=='wheel_positions':\n", " return self.left_wheel.position, self.middle_wheel.position, self.right_wheel.position \n", " elif name=='wheel_positions_l':\n", " return self.left_wheel.position_l, self.middle_wheel.position_l, self.right_wheel.position_l \n", " elif name=='peg_positions':\n", " return self.left_wheel.peg_positions, self.middle_wheel.peg_positions, self.right_wheel.peg_positions\n", " else:\n", " return object.__getattribute__(self, name)\n", "\n", " \n", " def set_wheels(self, left_wheel_position, middle_wheel_position, right_wheel_position):\n", " self.left_wheel.set_position(left_wheel_position)\n", " self.middle_wheel.set_position(middle_wheel_position)\n", " self.right_wheel.set_position(right_wheel_position)\n", " \n", " def lookup(self, letter):\n", " a = self.plugboard.forward(letter)\n", " b = self.right_wheel.forward(a)\n", " c = self.middle_wheel.forward(b)\n", " d = self.left_wheel.forward(c)\n", " e = self.reflector.forward(d)\n", " f = self.left_wheel.backward(e)\n", " g = self.middle_wheel.backward(f)\n", " h = self.right_wheel.backward(g)\n", " i = self.plugboard.backward(h)\n", " return i\n", " \n", " def advance(self):\n", " advance_middle = False\n", " advance_left = False\n", " if 0 in self.right_wheel.peg_positions:\n", " advance_middle = True\n", " if 0 in self.middle_wheel.peg_positions:\n", " advance_left = True\n", " advance_middle = True\n", " self.right_wheel.advance()\n", " if advance_middle: self.middle_wheel.advance()\n", " if advance_left: self.left_wheel.advance()\n", " \n", " def encipher_letter(self, letter):\n", " self.advance()\n", " return self.lookup(letter)\n", " \n", " def encipher(self, message, debug=False):\n", " enciphered = ''\n", " for letter in clean(message):\n", " enciphered += self.encipher_letter(letter)\n", " if debug:\n", " print('Wheels now', list(self.wheel_positions_l), 'enciphering {} -> {}'.format(letter, self.lookup(letter)))\n", " return enciphered" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\"('a', 'b', 'c')\"" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sfsdf = ('a', 'b', 'c')\n", "str(sfsdf)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": true }, "outputs": [], "source": [ "enigma = Enigma(reflector_b_spec, \n", " wheel_i_spec, wheel_i_pegs,\n", " wheel_ii_spec, wheel_ii_pegs,\n", " wheel_iii_spec, wheel_iii_pegs,\n", " 1, 1, 1,\n", " '')" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'u'" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.lookup('a')" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'a'" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.lookup('u')" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'uejobtpzwcnsrkdgvmlfaqiyxh'" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(enigma.lookup(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 :: a a a ; [16] [4] [21] uejobtpzwcnsrkdgvmlfaqiyxh\n", "1 :: a a b ; [16] [4] [20] baqmfexihswpdytlcvjozrkgnu\n", "2 :: a a c ; [16] [4] [19] djralkwpobfeyqihncxzvugsmt\n", "3 :: a a d ; [16] [4] [18] zlejcuitgdmbkonsvxphfqyrwa\n", "4 :: a a e ; [16] [4] [17] gcblwtakqzhdosmxiunfryepvj\n", "5 :: a a f ; [16] [4] [16] osnirgfmdpvuhcajwebxlkqtzy\n", "6 :: a a g ; [16] [4] [15] wymvnqzjlhoicekuftxrpdasbg\n", "7 :: a a h ; [16] [4] [14] cjafkdztpbeuormiwnvhlsqyxg\n", "8 :: a a i ; [16] [4] [13] xijuyslvbczgnmqwotfrdhpaek\n", "9 :: a a j ; [16] [4] [12] lfzrwbytjisaovmuxdkhpneqgc\n", "10 :: a a k ; [16] [4] [11] tkezcqynuwbpvhslfxoaimjrgd\n", "11 :: a a l ; [16] [4] [10] kiwfnduxbsaotelqpvjmgrchzy\n", "12 :: a a m ; [16] [4] [9] sfkutbpoxycrnmhgwlaedzqijv\n", "13 :: a a n ; [16] [4] [8] baqwlkhgrsfextpocijnvudmzy\n", "14 :: a a o ; [16] [4] [7] teofbdzxqkjyrscvimnawpuhlg\n", "15 :: a a p ; [16] [4] [6] mhypswrbzxqvaondkgeutlfjci\n", "16 :: a a q ; [16] [4] [5] cpasnrhgkuixzevbyfdwjotlqm\n", "17 :: a a r ; [16] [4] [4] dlfatcjwygvbnmzrxpueskhqio\n", "18 :: a a s ; [16] [4] [3] lxymzjuqtfpadsrkhonigwvbce\n", "19 :: a a t ; [16] [4] [2] puvioztjdhxmlyeawsrgbcqknf\n", "20 :: a a u ; [16] [4] [1] baigpldqcowfyzjehvtsxrkumn\n", "21 :: a a v ; [16] [4] [0] mnvfydiwgzsoablrxpkutchqej\n", "22 :: a b w ; [16] [3] [25] ulfopcykswhbzvderqixanjtgm\n", "23 :: a b x ; [16] [3] [24] qmwftdyovursbzhxaklejicpgn\n", "24 :: a b y ; [16] [3] [23] oljmzxrvucybdqasngpwihtfke\n", "25 :: a b z ; [16] [3] [22] fwevcalzxutgysrqponkjdbimh\n" ] } ], "source": [ "enigma.set_wheels('a', 'a', 'a')\n", "for i in range(26):\n", " print(i, '::', \n", " enigma.left_wheel.position_l, enigma.middle_wheel.position_l, enigma.right_wheel.position_l, ';',\n", " enigma.left_wheel.peg_positions, enigma.middle_wheel.peg_positions, enigma.right_wheel.peg_positions, \n", " cat(enigma.lookup(l) for l in string.ascii_lowercase))\n", " enigma.advance()" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": true, "scrolled": true }, "outputs": [], "source": [ "enigma.set_wheels('a', 'a', 't')\n", "assert(enigma.wheel_positions == (0, 0, 19))\n", "assert(cat(enigma.wheel_positions_l) == 'aat')\n", "assert(enigma.peg_positions == ([16], [4], [2]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'puvioztjdhxmlyeawsrgbcqknf')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 0, 20))\n", "assert(cat(enigma.wheel_positions_l) == 'aau')\n", "assert(enigma.peg_positions == ([16], [4], [1]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baigpldqcowfyzjehvtsxrkumn')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 0, 21))\n", "assert(cat(enigma.wheel_positions_l) == 'aav')\n", "assert(enigma.peg_positions == ([16], [4], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mnvfydiwgzsoablrxpkutchqej')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 1, 22))\n", "assert(cat(enigma.wheel_positions_l) == 'abw')\n", "assert(enigma.peg_positions == ([16], [3], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ulfopcykswhbzvderqixanjtgm')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 1, 23))\n", "assert(cat(enigma.wheel_positions_l) == 'abx')\n", "assert(enigma.peg_positions == ([16], [3], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qmwftdyovursbzhxaklejicpgn')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 1, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'aby')\n", "assert(enigma.peg_positions == ([16], [3], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'oljmzxrvucybdqasngpwihtfke')\n" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 5, 24) ('b', 'f', 'y') ([15], [25], [23]) baknstqzrmcxjdvygiefwoulph\n" ] } ], "source": [ "enigma.set_wheels('a', 'd', 't')\n", "assert(enigma.wheel_positions == (0, 3, 19))\n", "assert(cat(enigma.wheel_positions_l) == 'adt')\n", "assert(enigma.peg_positions == ([16], [1], [2]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zcbpqxwsjiuonmldethrkygfva')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 3, 20))\n", "assert(cat(enigma.wheel_positions_l) == 'adu')\n", "assert(enigma.peg_positions == ([16], [1], [1]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ehprawjbngotxikcsdqlzyfmvu')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 3, 21))\n", "assert(cat(enigma.wheel_positions_l) == 'adv')\n", "assert(enigma.peg_positions == ([16], [1], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'eqzxarpihmnvjkwgbfuyslodtc')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (0, 4, 22))\n", "assert(cat(enigma.wheel_positions_l) == 'aew')\n", "assert(enigma.peg_positions == ([16], [0], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qedcbtpluzmhkongavwfirsyxj')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 23))\n", "assert(cat(enigma.wheel_positions_l) == 'bfx')\n", "assert(enigma.peg_positions == ([15], [25], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'iwuedhsfazqxytvrkpgncoblmj')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'bfy')\n", "assert(enigma.peg_positions == ([15], [25], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baknstqzrmcxjdvygiefwoulph')\n", "\n", "print(enigma.wheel_positions, enigma.wheel_positions_l, enigma.peg_positions, \n", " cat(enigma.lookup(l) for l in string.ascii_lowercase))\n" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'olpfhnvflyn'" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.set_wheels('a', 'a', 'a')\n", "ct = enigma.encipher('testmessage')\n", "assert(ct == 'olpfhnvflyn')\n", "ct" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'lawnjgpwjik'" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.set_wheels('a', 'd', 't')\n", "ct = enigma.encipher('testmessage')\n", "assert(ct == 'lawnjgpwjik')\n", "ct" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 5))\n", "assert(cat(enigma.wheel_positions_l) == 'bff')\n", "assert(enigma.peg_positions == ([15], [25], [16]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zpqiogfsdlmjkyebcvhxwrutna')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 6))\n", "assert(cat(enigma.wheel_positions_l) == 'bfg')\n", "assert(enigma.peg_positions == ([15], [25], [15]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'fjmnwayslbxicdpouthrqzekgv')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 7))\n", "assert(cat(enigma.wheel_positions_l) == 'bfh')\n", "assert(enigma.peg_positions == ([15], [25], [14]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'csafzdyloxuhnmitwvbpkrqjge')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 8))\n", "assert(cat(enigma.wheel_positions_l) == 'bfi')\n", "assert(enigma.peg_positions == ([15], [25], [13]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'kihyvulcbtagwrqzonxjfemsdp')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 9))\n", "assert(cat(enigma.wheel_positions_l) == 'bfj')\n", "assert(enigma.peg_positions == ([15], [25], [12]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pgzrytbksqhwxvuajdifonlmec')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 10))\n", "assert(cat(enigma.wheel_positions_l) == 'bfk')\n", "assert(enigma.peg_positions == ([15], [25], [11]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'fkirsazncwbvyhpoudexqljtmg')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 11))\n", "assert(cat(enigma.wheel_positions_l) == 'bfl')\n", "assert(enigma.peg_positions == ([15], [25], [10]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mhkronubsvctafeqpdilgjxwzy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 12))\n", "assert(cat(enigma.wheel_positions_l) == 'bfm')\n", "assert(enigma.peg_positions == ([15], [25], [9]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'gnkuoxarzycmlbetvhwpdqsfji')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 13))\n", "assert(cat(enigma.wheel_positions_l) == 'bfn')\n", "assert(enigma.peg_positions == ([15], [25], [8]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'bainslqkcxhfudpogtermwvjzy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 14))\n", "assert(cat(enigma.wheel_positions_l) == 'bfo')\n", "assert(enigma.peg_positions == ([15], [25], [7]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xemfbdnwjitycgzusvqkprhalo')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 15))\n", "assert(cat(enigma.wheel_positions_l) == 'bfp')\n", "assert(enigma.peg_positions == ([15], [25], [6]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qixksmhgbtdvfonrapejwluczy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 16))\n", "assert(cat(enigma.wheel_positions_l) == 'bfq')\n", "assert(enigma.peg_positions == ([15], [25], [5]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cgaulmbskwiefrtzynhodxjvqp')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 17))\n", "assert(cat(enigma.wheel_positions_l) == 'bfr')\n", "assert(enigma.peg_positions == ([15], [25], [4]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'iwqfldszaxvenmyrcpgutkbjoh')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 18))\n", "assert(cat(enigma.wheel_positions_l) == 'bfs')\n", "assert(enigma.peg_positions == ([15], [25], [3]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vxykrjilgfdhqtusmepnoazbcw')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 19))\n", "assert(cat(enigma.wheel_positions_l) == 'bft')\n", "assert(enigma.peg_positions == ([15], [25], [2]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ieysbvkjahgmlpxnwtdrzfqocu')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 20))\n", "assert(cat(enigma.wheel_positions_l) == 'bfu')\n", "assert(enigma.peg_positions == ([15], [25], [1]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'baihkjvdcfepywsltxoqzgnrmu')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 5, 21))\n", "assert(cat(enigma.wheel_positions_l) == 'bfv')\n", "assert(enigma.peg_positions == ([15], [25], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'bayjtrilgdshvzuwxfkeompqcn')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 22))\n", "assert(cat(enigma.wheel_positions_l) == 'bgw')\n", "assert(enigma.peg_positions == ([15], [24], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'rszqohpfxyutvwegdablkmnijc')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 23))\n", "assert(cat(enigma.wheel_positions_l) == 'bgx')\n", "assert(enigma.peg_positions == ([15], [24], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nfoxhbzeyrwqpacmljtsvukdig')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'bgy')\n", "assert(enigma.peg_positions == ([15], [24], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'czaogmeihtuqfsdxlwnjkyrpvb')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 25))\n", "assert(cat(enigma.wheel_positions_l) == 'bgz')\n", "assert(enigma.peg_positions == ([15], [24], [22]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'omwgysdjkhizbxarupfvqtcnel')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 0))\n", "assert(cat(enigma.wheel_positions_l) == 'bga')\n", "assert(enigma.peg_positions == ([15], [24], [21]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cxafmdrzoqutepinjgvlksybwh')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 1))\n", "assert(cat(enigma.wheel_positions_l) == 'bgb')\n", "assert(enigma.peg_positions == ([15], [24], [20]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'jymvnrxkoahwceiuzftspdlgbq')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 2))\n", "assert(cat(enigma.wheel_positions_l) == 'bgc')\n", "assert(enigma.peg_positions == ([15], [24], [19]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'uzlyiqwrestcnmxvfhjkapgodb')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 3))\n", "assert(cat(enigma.wheel_positions_l) == 'bgd')\n", "assert(enigma.peg_positions == ([15], [24], [18]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'veosbuhgpzqynmcikwdxfartlj')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (1, 6, 4))\n", "assert(cat(enigma.wheel_positions_l) == 'bge')\n", "assert(enigma.peg_positions == ([15], [24], [17]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ydhbmtrclxsiezpougkfqwvjan')\n", "\n" ] } ], "source": [ "\n", "for i in range(26):\n", " enigma.advance()\n", " print('enigma.advance()')\n", " print(\"assert(enigma.wheel_positions == {})\".format(enigma.wheel_positions))\n", " print(\"assert(cat(enigma.wheel_positions_l) == '{}')\".format(cat(enigma.wheel_positions_l)))\n", " print(\"assert(enigma.peg_positions == {})\".format(enigma.peg_positions))\n", " print(\"assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == '{}')\".format(cat(enigma.lookup(l) for l in string.ascii_lowercase)))\n", " print()" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'bahxvfrpdc'" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.set_wheels('a', 'd', 't')\n", "ct = enigma.encipher('hellothere')\n", "assert(ct == 'bahxvfrpdc')\n", "ct" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr'" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.set_wheels('b', 'd', 'q')\n", "ct = enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')\n", "assert(ct == 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr')\n", "assert(enigma.left_wheel.position_l == 'c')\n", "assert(enigma.middle_wheel.position_l == 'h')\n", "assert(enigma.right_wheel.position_l == 'a')\n", "ct" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'c'" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.left_wheel.position_l" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n", "# Enigma simulation settings are \n", "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n", "w_enigma = Enigma(reflector_b_spec, \n", " wheel_i_spec, wheel_i_pegs,\n", " wheel_v_spec, wheel_v_pegs,\n", " wheel_iii_spec, wheel_iii_pegs,\n", " 6, 20, 24,\n", " 'ua pf rq so ni ey bg hl tx zj')" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm\n", "# Enigma simulation settings are \n", "# http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJFE;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX\n", "enigma = Enigma(reflector_b_spec, \n", " wheel_i_spec, wheel_i_pegs,\n", " wheel_v_spec, wheel_v_pegs,\n", " wheel_iii_spec, wheel_iii_pegs,\n", " 6, 20, 24,\n", " 'ua pf rq so ni ey bg hl tx zj')" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": true }, "outputs": [], "source": [ "enigma.set_wheels('j', 'e', 'u')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (4, 11, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'jev')\n", "assert(enigma.peg_positions == ([7], [21], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mvqjlyowkdieasgzcunxrbhtfp')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (4, 12, 25))\n", "assert(cat(enigma.wheel_positions_l) == 'jfw')\n", "assert(enigma.peg_positions == ([7], [20], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'sjolzuyvrbwdpxcmtiaqfhknge')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (4, 12, 0))\n", "assert(cat(enigma.wheel_positions_l) == 'jfx')\n", "assert(enigma.peg_positions == ([7], [20], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qrxedkoywufmlvgsabpzjnicht')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (4, 12, 1))\n", "assert(cat(enigma.wheel_positions_l) == 'jfy')\n", "assert(enigma.peg_positions == ([7], [20], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hpsukliagqefwvtbjxcodnmrzy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (4, 12, 2))\n", "assert(cat(enigma.wheel_positions_l) == 'jfz')\n", "assert(enigma.peg_positions == ([7], [20], [22]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'zevnbpyqowrtxdifhkulscjmga')\n" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": true }, "outputs": [], "source": [ "enigma.set_wheels('i', 'd', 'z')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 3))\n", "assert(cat(enigma.wheel_positions_l) == 'ida')\n", "assert(enigma.peg_positions == ([8], [22], [21]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ikhpqrvcambzjondefwyxgsutl')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 4))\n", "assert(cat(enigma.wheel_positions_l) == 'idb')\n", "assert(enigma.peg_positions == ([8], [22], [20]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cdabskhgzwfmlqvunyexpojtri')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 5))\n", "assert(cat(enigma.wheel_positions_l) == 'idc')\n", "assert(enigma.peg_positions == ([8], [22], [19]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pcbwiqhgemyvjsuaftnroldzkx')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 6))\n", "assert(cat(enigma.wheel_positions_l) == 'idd')\n", "assert(enigma.peg_positions == ([8], [22], [18]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xcbfvdnouptmlghjzwykierasq')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 7))\n", "assert(cat(enigma.wheel_positions_l) == 'ide')\n", "assert(enigma.peg_positions == ([8], [22], [17]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xfvglbdynuseriwqpmkzjcoaht')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 8))\n", "assert(cat(enigma.wheel_positions_l) == 'idf')\n", "assert(enigma.peg_positions == ([8], [22], [16]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'tfpqlbouynsewjgcdxkahzmriv')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 9))\n", "assert(cat(enigma.wheel_positions_l) == 'idg')\n", "assert(enigma.peg_positions == ([8], [22], [15]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cjaunvlwtbygzexrspqidfhokm')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 10))\n", "assert(cat(enigma.wheel_positions_l) == 'idh')\n", "assert(enigma.peg_positions == ([8], [22], [14]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yltxkrqvowebzpingfucshjdam')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 11))\n", "assert(cat(enigma.wheel_positions_l) == 'idi')\n", "assert(enigma.peg_positions == ([8], [22], [13]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'myktluzrnxceaiqsohpdfwvjbg')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 12))\n", "assert(cat(enigma.wheel_positions_l) == 'idj')\n", "assert(enigma.peg_positions == ([8], [22], [12]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pynjrmiugdqxfcvakewzhoslbt')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 13))\n", "assert(cat(enigma.wheel_positions_l) == 'idk')\n", "assert(enigma.peg_positions == ([8], [22], [11]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mwvedyplnoxhaijgrqtszcbkfu')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 14))\n", "assert(cat(enigma.wheel_positions_l) == 'idl')\n", "assert(enigma.peg_positions == ([8], [22], [10]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qcbrfeutvoxpnmjladzhgiykws')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 15))\n", "assert(cat(enigma.wheel_positions_l) == 'idm')\n", "assert(enigma.peg_positions == ([8], [22], [9]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'dnoahryetsmukbcvwfjilpqzgx')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 16))\n", "assert(cat(enigma.wheel_positions_l) == 'idn')\n", "assert(enigma.peg_positions == ([8], [22], [8]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nidcfehgbqsovalyjzkxwmutpr')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 17))\n", "assert(cat(enigma.wheel_positions_l) == 'ido')\n", "assert(enigma.peg_positions == ([8], [22], [7]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'joifxdulcarhzpbntkwqgysevm')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 18))\n", "assert(cat(enigma.wheel_positions_l) == 'idp')\n", "assert(enigma.peg_positions == ([8], [22], [6]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ptnlsxvozmwdjchayuebrgkfqi')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 19))\n", "assert(cat(enigma.wheel_positions_l) == 'idq')\n", "assert(enigma.peg_positions == ([8], [22], [5]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'slwopzqnmxybihdeguavrtcjkf')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 20))\n", "assert(cat(enigma.wheel_positions_l) == 'idr')\n", "assert(enigma.peg_positions == ([8], [22], [4]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hcbedwlamzogixkytsrqvufnpj')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 21))\n", "assert(cat(enigma.wheel_positions_l) == 'ids')\n", "assert(enigma.peg_positions == ([8], [22], [3]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'odxbjwzrmelkisavuhnyqpfctg')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 22))\n", "assert(cat(enigma.wheel_positions_l) == 'idt')\n", "assert(enigma.peg_positions == ([8], [22], [2]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'udgbfeclrwnhxksvtioqapjmzy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 23))\n", "assert(cat(enigma.wheel_positions_l) == 'idu')\n", "assert(enigma.peg_positions == ([8], [22], [1]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nrdczqxmowvshaiufblypkjgte')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'idv')\n", "assert(enigma.peg_positions == ([8], [22], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hkifjdoacebqtzgulyvmpsxwrn')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 25))\n", "assert(cat(enigma.wheel_positions_l) == 'iew')\n", "assert(enigma.peg_positions == ([8], [21], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yptzuhofqvnmlkgbixwcejsrad')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 0))\n", "assert(cat(enigma.wheel_positions_l) == 'iex')\n", "assert(enigma.peg_positions == ([8], [21], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vkdcwhqfjibzsptngumoraeyxl')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 1))\n", "assert(cat(enigma.wheel_positions_l) == 'iey')\n", "assert(enigma.peg_positions == ([8], [21], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'wenpbqrouxlkychdfgzvitajms')\n" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('verylongtestmessagewithanextrabitofmessageforgoodmeasure',\n", " (3, 12, 6),\n", " ('i', 'f', 'd'),\n", " ([8], [20], [18]),\n", " 'urygzpdmxtwshqvfnbljaokice')" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "enigma.set_wheels('i', 'd', 'z')\n", "ct = enigma.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n", "assert(ct == 'gstsegeqdrthkfwesljjomfvcqwcfspxpfqqmewvddybarzwubxtpejz')\n", "assert(enigma.wheel_positions == (3, 12, 6))\n", "assert(cat(enigma.wheel_positions_l) == 'ifd')\n", "assert(enigma.peg_positions == ([8], [20], [18]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'urygzpdmxtwshqvfnbljaokice')\n", "\n", "enigma.set_wheels('i', 'd', 'z')\n", "pt = enigma.encipher('gstsegeqdrthkfwesljjomfvcqwcfspxpfqqmewvddybarzwubxtpejz')\n", "assert(pt == 'verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n", "\n", "pt, enigma.wheel_positions, enigma.wheel_positions_l, enigma.peg_positions, cat(enigma.lookup(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 3))\n", "assert(cat(enigma.wheel_positions_l) == 'ida')\n", "assert(enigma.peg_positions == ([8], [22], [21]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ikhpqrvcambzjondefwyxgsutl')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 4))\n", "assert(cat(enigma.wheel_positions_l) == 'idb')\n", "assert(enigma.peg_positions == ([8], [22], [20]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cdabskhgzwfmlqvunyexpojtri')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 5))\n", "assert(cat(enigma.wheel_positions_l) == 'idc')\n", "assert(enigma.peg_positions == ([8], [22], [19]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pcbwiqhgemyvjsuaftnroldzkx')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 6))\n", "assert(cat(enigma.wheel_positions_l) == 'idd')\n", "assert(enigma.peg_positions == ([8], [22], [18]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xcbfvdnouptmlghjzwykierasq')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 7))\n", "assert(cat(enigma.wheel_positions_l) == 'ide')\n", "assert(enigma.peg_positions == ([8], [22], [17]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'xfvglbdynuseriwqpmkzjcoaht')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 8))\n", "assert(cat(enigma.wheel_positions_l) == 'idf')\n", "assert(enigma.peg_positions == ([8], [22], [16]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'tfpqlbouynsewjgcdxkahzmriv')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 9))\n", "assert(cat(enigma.wheel_positions_l) == 'idg')\n", "assert(enigma.peg_positions == ([8], [22], [15]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'cjaunvlwtbygzexrspqidfhokm')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 10))\n", "assert(cat(enigma.wheel_positions_l) == 'idh')\n", "assert(enigma.peg_positions == ([8], [22], [14]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yltxkrqvowebzpingfucshjdam')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 11))\n", "assert(cat(enigma.wheel_positions_l) == 'idi')\n", "assert(enigma.peg_positions == ([8], [22], [13]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'myktluzrnxceaiqsohpdfwvjbg')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 12))\n", "assert(cat(enigma.wheel_positions_l) == 'idj')\n", "assert(enigma.peg_positions == ([8], [22], [12]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'pynjrmiugdqxfcvakewzhoslbt')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 13))\n", "assert(cat(enigma.wheel_positions_l) == 'idk')\n", "assert(enigma.peg_positions == ([8], [22], [11]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'mwvedyplnoxhaijgrqtszcbkfu')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 14))\n", "assert(cat(enigma.wheel_positions_l) == 'idl')\n", "assert(enigma.peg_positions == ([8], [22], [10]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'qcbrfeutvoxpnmjladzhgiykws')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 15))\n", "assert(cat(enigma.wheel_positions_l) == 'idm')\n", "assert(enigma.peg_positions == ([8], [22], [9]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'dnoahryetsmukbcvwfjilpqzgx')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 16))\n", "assert(cat(enigma.wheel_positions_l) == 'idn')\n", "assert(enigma.peg_positions == ([8], [22], [8]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nidcfehgbqsovalyjzkxwmutpr')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 17))\n", "assert(cat(enigma.wheel_positions_l) == 'ido')\n", "assert(enigma.peg_positions == ([8], [22], [7]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'joifxdulcarhzpbntkwqgysevm')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 18))\n", "assert(cat(enigma.wheel_positions_l) == 'idp')\n", "assert(enigma.peg_positions == ([8], [22], [6]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'ptnlsxvozmwdjchayuebrgkfqi')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 19))\n", "assert(cat(enigma.wheel_positions_l) == 'idq')\n", "assert(enigma.peg_positions == ([8], [22], [5]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'slwopzqnmxybihdeguavrtcjkf')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 20))\n", "assert(cat(enigma.wheel_positions_l) == 'idr')\n", "assert(enigma.peg_positions == ([8], [22], [4]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hcbedwlamzogixkytsrqvufnpj')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 21))\n", "assert(cat(enigma.wheel_positions_l) == 'ids')\n", "assert(enigma.peg_positions == ([8], [22], [3]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'odxbjwzrmelkisavuhnyqpfctg')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 22))\n", "assert(cat(enigma.wheel_positions_l) == 'idt')\n", "assert(enigma.peg_positions == ([8], [22], [2]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'udgbfeclrwnhxksvtioqapjmzy')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 23))\n", "assert(cat(enigma.wheel_positions_l) == 'idu')\n", "assert(enigma.peg_positions == ([8], [22], [1]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'nrdczqxmowvshaiufblypkjgte')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 10, 24))\n", "assert(cat(enigma.wheel_positions_l) == 'idv')\n", "assert(enigma.peg_positions == ([8], [22], [0]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'hkifjdoacebqtzgulyvmpsxwrn')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 25))\n", "assert(cat(enigma.wheel_positions_l) == 'iew')\n", "assert(enigma.peg_positions == ([8], [21], [25]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'yptzuhofqvnmlkgbixwcejsrad')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 0))\n", "assert(cat(enigma.wheel_positions_l) == 'iex')\n", "assert(enigma.peg_positions == ([8], [21], [24]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'vkdcwhqfjibzsptngumoraeyxl')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 1))\n", "assert(cat(enigma.wheel_positions_l) == 'iey')\n", "assert(enigma.peg_positions == ([8], [21], [23]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'wenpbqrouxlkychdfgzvitajms')\n", "\n", "enigma.advance()\n", "assert(enigma.wheel_positions == (3, 11, 2))\n", "assert(cat(enigma.wheel_positions_l) == 'iez')\n", "assert(enigma.peg_positions == ([8], [21], [22]))\n", "assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == 'szgyqvclkoihurjwenaxmfptdb')\n", "\n" ] } ], "source": [ "enigma.set_wheels('i', 'd', 'z')\n", "\n", "for i in range(26):\n", " enigma.advance()\n", " print('enigma.advance()')\n", " print(\"assert(enigma.wheel_positions == {})\".format(enigma.wheel_positions))\n", " print(\"assert(cat(enigma.wheel_positions_l) == '{}')\".format(cat(enigma.wheel_positions_l)))\n", " print(\"assert(enigma.peg_positions == {})\".format(enigma.peg_positions))\n", " print(\"assert(cat(enigma.lookup(l) for l in string.ascii_lowercase) == '{}')\".format(cat(enigma.lookup(l) for l in string.ascii_lowercase)))\n", " print()" ] }, { "cell_type": "code", "execution_count": 86, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Reflector B\n", "# Rotors III, I, II with rings 17, 11, 19\n", "# Plugboard pairs GU FZ BD LK TC PS HV WN JE AM\n", "\n", "tbt_enigma = Enigma(reflector_b_spec, \n", " wheel_iii_spec, wheel_iii_pegs,\n", " wheel_i_spec, wheel_i_pegs,\n", " wheel_ii_spec, wheel_ii_pegs,\n", " 17, 11, 19,\n", " 'GU FZ BD LK TC PS HV WN JE AM'.lower())" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'jbvbwwzfslhxnhzzccsngebmrnswgjonwbjnzcfgadeuoyameylmpvny'" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tbt_enigma.set_wheels('a', 'q', 'v')\n", "ct = tbt_enigma.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')\n", "ct" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'slgncszxltkzebghstgywdmpr'" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "target_ct = ''.join(c.lower() for c in 'SLGNC SZXLT KZEBG HSTGY WDMPR' if c in string.ascii_letters)\n", "target_ct" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'theyweredetectebybritishshipsinclud'" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "target_pt = ''.join(c.lower() for c in 'Theyw erede tecte byBri tishs hipsi nclud' if c in string.ascii_letters)\n", "target_pt" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'theyweredetectedbybritishshipsinclud'" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "target_pt = ''.join(c.lower() for c in 'Theyw erede tecte d byBri tishs hipsi nclud' if c in string.ascii_letters)\n", "target_pt" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(25, 35)" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(target_ct), len(target_pt)" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "slgncszxltkzebghstgywdmpr\n", "theyweredetectebybritishshipsinclud\n" ] } ], "source": [ "print('{}\\n{}'.format(target_ct, target_pt))" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "theyweredetectedbybritishshipsinclud\n", "slgncszxltkzebghstgywdmpr\n", "slgncszxltkzebghstgywdmprucuzqdqzpve\n", "theyweredetectedbybritish\n" ] } ], "source": [ "tbt_enigma.set_wheels('a', 'a', 'a')\n", "this_pt = tbt_enigma.encipher(target_ct)\n", "\n", "tbt_enigma.set_wheels('a', 'a', 'a')\n", "this_ct = tbt_enigma.encipher(target_pt)\n", "\n", "\n", "print('{}\\n{}\\n{}\\n{}'.format(target_pt, target_ct, this_ct, this_pt))" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import itertools" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def str_ham(s1, s2):\n", " \"\"\"Hamming distance for strings\"\"\"\n", " return sum(1 for c1, c2 in zip(s1, s2) if c1 == c2)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "str_ham('hello', 'hello')" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "best ('a', 'a', 'a') 25\n", "best ('a', 'a', 'a') 25\n", "best ('a', 'a', 'a') 25\n", "best ('a', 'a', 'a') 25\n", "1 loop, best of 3: 17.6 s per loop\n" ] } ], "source": [ "%%timeit\n", "best = ('a', 'a', 'a')\n", "best_hd = 0\n", "for w1, w2, w3 in itertools.product(string.ascii_lowercase, repeat=3):\n", " tbt_enigma.set_wheels(w1, w2, w3)\n", " this_ct = tbt_enigma.encipher(target_pt)\n", " if this_ct == target_ct:\n", " print(w1, w2, w3)\n", " if str_ham(this_ct, target_ct) > best_hd:\n", " best = (w1, w2, w3)\n", " best_hd = str_ham(this_ct, target_ct)\n", "print('best', best, best_hd)" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wheels now ['a', 'a', 'b'] enciphering t -> s\n", "Wheels now ['a', 'a', 'c'] enciphering h -> l\n", "Wheels now ['a', 'a', 'd'] enciphering e -> g\n", "Wheels now ['a', 'a', 'e'] enciphering y -> n\n", "Wheels now ['a', 'b', 'f'] enciphering w -> c\n", "Wheels now ['a', 'b', 'g'] enciphering e -> s\n", "Wheels now ['a', 'b', 'h'] enciphering r -> z\n", "Wheels now ['a', 'b', 'i'] enciphering e -> x\n", "Wheels now ['a', 'b', 'j'] enciphering d -> l\n", "Wheels now ['a', 'b', 'k'] enciphering e -> t\n", "Wheels now ['a', 'b', 'l'] enciphering t -> k\n", "Wheels now ['a', 'b', 'm'] enciphering e -> z\n", "Wheels now ['a', 'b', 'n'] enciphering c -> e\n", "Wheels now ['a', 'b', 'o'] enciphering t -> b\n", "Wheels now ['a', 'b', 'p'] enciphering e -> g\n", "Wheels now ['a', 'b', 'q'] enciphering d -> h\n", "Wheels now ['a', 'b', 'r'] enciphering b -> s\n", "Wheels now ['a', 'b', 's'] enciphering y -> t\n", "Wheels now ['a', 'b', 't'] enciphering b -> g\n", "Wheels now ['a', 'b', 'u'] enciphering r -> y\n", "Wheels now ['a', 'b', 'v'] enciphering i -> w\n", "Wheels now ['a', 'b', 'w'] enciphering t -> d\n", "Wheels now ['a', 'b', 'x'] enciphering i -> m\n", "Wheels now ['a', 'b', 'y'] enciphering s -> p\n", "Wheels now ['a', 'b', 'z'] enciphering h -> r\n", "Wheels now ['a', 'b', 'a'] enciphering s -> u\n", "Wheels now ['a', 'b', 'b'] enciphering h -> c\n", "Wheels now ['a', 'b', 'c'] enciphering i -> u\n", "Wheels now ['a', 'b', 'd'] enciphering p -> z\n", "Wheels now ['a', 'b', 'e'] enciphering s -> q\n", "Wheels now ['a', 'c', 'f'] enciphering i -> d\n", "Wheels now ['a', 'c', 'g'] enciphering n -> q\n", "Wheels now ['a', 'c', 'h'] enciphering c -> z\n", "Wheels now ['a', 'c', 'i'] enciphering l -> p\n", "Wheels now ['a', 'c', 'j'] enciphering u -> v\n", "Wheels now ['a', 'c', 'k'] enciphering d -> e\n" ] }, { "data": { "text/plain": [ "('slgncszxltkzebghstgywdmprucuzqdqzpve', 'slgncszxltkzebghstgywdmpr')" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tbt_enigma.set_wheels('a', 'a', 'a')\n", "tbt_enigma.encipher(target_pt, debug=True), target_ct" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wheels now ['a', 'a', 'b'] enciphering s -> t\n", "Wheels now ['a', 'a', 'c'] enciphering l -> h\n", "Wheels now ['a', 'a', 'd'] enciphering g -> e\n", "Wheels now ['a', 'a', 'e'] enciphering n -> y\n", "Wheels now ['a', 'b', 'f'] enciphering c -> w\n", "Wheels now ['a', 'b', 'g'] enciphering s -> e\n", "Wheels now ['a', 'b', 'h'] enciphering z -> r\n", "Wheels now ['a', 'b', 'i'] enciphering x -> e\n", "Wheels now ['a', 'b', 'j'] enciphering l -> d\n", "Wheels now ['a', 'b', 'k'] enciphering t -> e\n", "Wheels now ['a', 'b', 'l'] enciphering k -> t\n", "Wheels now ['a', 'b', 'm'] enciphering z -> e\n", "Wheels now ['a', 'b', 'n'] enciphering e -> c\n", "Wheels now ['a', 'b', 'o'] enciphering b -> t\n", "Wheels now ['a', 'b', 'p'] enciphering g -> e\n", "Wheels now ['a', 'b', 'q'] enciphering h -> d\n", "Wheels now ['a', 'b', 'r'] enciphering s -> b\n", "Wheels now ['a', 'b', 's'] enciphering t -> y\n", "Wheels now ['a', 'b', 't'] enciphering g -> b\n", "Wheels now ['a', 'b', 'u'] enciphering y -> r\n", "Wheels now ['a', 'b', 'v'] enciphering w -> i\n", "Wheels now ['a', 'b', 'w'] enciphering d -> t\n", "Wheels now ['a', 'b', 'x'] enciphering m -> i\n", "Wheels now ['a', 'b', 'y'] enciphering p -> s\n", "Wheels now ['a', 'b', 'z'] enciphering r -> h\n" ] }, { "data": { "text/plain": [ "('theyweredetectedbybritish', 'theyweredetectedbybritishshipsinclud')" ] }, "execution_count": 95, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tbt_enigma.set_wheels('a', 'a', 'a')\n", "tbt_enigma.encipher(target_ct, debug=True), target_pt" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('theyweredetectedbybritish', 'theyweredetectedbybritishshipsinclud')" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tbt_enigma.set_wheels('a', 'a', 'a')\n", "tbt_enigma.encipher(target_ct), target_pt" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'mdtbjzuvielkawosqrpcghnxyf'" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(tbt_enigma.plugboard.forward(l) for l in string.ascii_lowercase)" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tbt_enigma.set_wheels('a', 'a', 'a')\n", "tbt_enigma.left_wheel.position" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.3" } }, "nbformat": 4, "nbformat_minor": 1 }