--- /dev/null
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "from enigma import *"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "e31 = 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')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def advance(e, n):\n",
+ " def print_state(e):\n",
+ " print(' self.assertEqual(self.enigma31.wheel_positions, {})'.format(e.wheel_positions))\n",
+ " print(\" self.assertEqual(cat(self.enigma31.wheel_positions_l), '{}')\".format(cat(e.wheel_positions_l)))\n",
+ " print(' self.assertEqual(self.enigma31.peg_positions, {})'.format(e.peg_positions))\n",
+ " print()\n",
+ " \n",
+ " \n",
+ " \n",
+ " print_state(e)\n",
+ " for i in range(n):\n",
+ " print(' self.engima31.advance()')\n",
+ " e.advance()\n",
+ " print_state(e)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " self.assertEqual(self.enigma31.wheel_positions, (21, 5, 22))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayt')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([16], [1], [2]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (21, 5, 23))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayu')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([16], [1], [1]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (21, 5, 24))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayv')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([16], [1], [0]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (21, 6, 25))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azw')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([16], [0], [25]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 7, 0))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bax')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [25], [24]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 7, 1))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bay')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [25], [23]))\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "e31.set_wheels('a', 'y', 't')\n",
+ "advance(e31, 5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " self.assertEqual(self.enigma31.wheel_positions, (21, 6, 21))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azs')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([16], [0], [3]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 7, 22))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bat')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [25], [2]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 7, 23))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bau')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [25], [1]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 7, 24))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bav')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [25], [0]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 8, 25))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbw')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [24], [25]))\n",
+ "\n",
+ " self.engima31.advance()\n",
+ " self.assertEqual(self.enigma31.wheel_positions, (22, 8, 0))\n",
+ " self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbx')\n",
+ " self.assertEqual(self.enigma31.peg_positions, ([15], [24], [24]))\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "e31.set_wheels('a', 'z', 's')\n",
+ "advance(e31, 5)"
+ ]
+ },
+ {
+ "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.1+"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
"cells": [
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 1,
"metadata": {
"collapsed": true
},
"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": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
"source": [
"Signal = collections.namedtuple('Signal', ['bank', 'wire'])\n",
"Connection = collections.namedtuple('Connection', ['banks', 'scrambler'])\n",
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 4,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 5,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 804,
+ "execution_count": 6,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 805,
+ "execution_count": 7,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 806,
+ "execution_count": 8,
"metadata": {
"collapsed": false
},
"'opgndxcrwomnlnecjz'"
]
},
- "execution_count": 806,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 807,
+ "execution_count": 9,
"metadata": {
"collapsed": false
},
"'aas'"
]
},
- "execution_count": 807,
+ "execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 808,
+ "execution_count": 10,
"metadata": {
"collapsed": false
},
" MenuIem(before='e', after='z', number=18)]"
]
},
- "execution_count": 808,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 809,
+ "execution_count": 11,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 810,
+ "execution_count": 12,
"metadata": {
"collapsed": false
},
" MenuIem(before='e', after='z', number=18)]"
]
},
- "execution_count": 810,
+ "execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 811,
+ "execution_count": 13,
"metadata": {
"collapsed": false
},
"'s'"
]
},
- "execution_count": 811,
+ "execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 812,
+ "execution_count": 14,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 813,
+ "execution_count": 15,
"metadata": {
"collapsed": false
},
"18"
]
},
- "execution_count": 813,
+ "execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 814,
+ "execution_count": 16,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 815,
+ "execution_count": 17,
"metadata": {
"collapsed": false
},
"False"
]
},
- "execution_count": 815,
+ "execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 816,
+ "execution_count": 18,
"metadata": {
"collapsed": false
},
" 'z': True}"
]
},
- "execution_count": 816,
+ "execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 817,
+ "execution_count": 19,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 818,
+ "execution_count": 20,
"metadata": {
"collapsed": false
},
"('a', 'a', 'a')"
]
},
- "execution_count": 818,
+ "execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 819,
+ "execution_count": 21,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 820,
+ "execution_count": 22,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 821,
+ "execution_count": 23,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 822,
+ "execution_count": 24,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 823,
+ "execution_count": 25,
"metadata": {
"collapsed": false
},
"1"
]
},
- "execution_count": 823,
+ "execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 824,
+ "execution_count": 26,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 825,
+ "execution_count": 27,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 826,
+ "execution_count": 28,
"metadata": {
"collapsed": false
},
"('a', 'a', 'b')"
]
},
- "execution_count": 826,
+ "execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 827,
+ "execution_count": 29,
"metadata": {
"collapsed": false
},
"False"
]
},
- "execution_count": 827,
+ "execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 828,
+ "execution_count": 30,
"metadata": {
"collapsed": false
},
"('p', 'p', 'p')"
]
},
- "execution_count": 828,
+ "execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 829,
+ "execution_count": 31,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 830,
+ "execution_count": 32,
"metadata": {
"collapsed": false
},
"17576"
]
},
- "execution_count": 830,
+ "execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 831,
+ "execution_count": 33,
"metadata": {
"collapsed": false
},
"(('a', 'a', 'b'), True)"
]
},
- "execution_count": 831,
+ "execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 832,
+ "execution_count": 34,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 833,
+ "execution_count": 35,
"metadata": {
"collapsed": false
},
"[('a', 'a', 'b')]"
]
},
- "execution_count": 833,
+ "execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 857,
+ "execution_count": 36,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 835,
+ "execution_count": 37,
"metadata": {
"collapsed": false
},
"[('a', 'a', 'b')]"
]
},
- "execution_count": 835,
+ "execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 836,
+ "execution_count": 38,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 837,
+ "execution_count": 39,
"metadata": {
"collapsed": false
},
"('e', 'l', 'e')"
]
},
- "execution_count": 837,
+ "execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 838,
+ "execution_count": 40,
"metadata": {
"collapsed": false
},
"'dhnpforeeimgg'"
]
},
- "execution_count": 838,
+ "execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 839,
+ "execution_count": 41,
"metadata": {
"collapsed": false
},
"('j', 'e', 'o')"
]
},
- "execution_count": 839,
+ "execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 840,
+ "execution_count": 42,
"metadata": {
"collapsed": false
},
" MenuIem(before='t', after='g', number=13)]"
]
},
- "execution_count": 840,
+ "execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 841,
+ "execution_count": 43,
"metadata": {
"collapsed": false,
"scrolled": true
" ('z', 'z', 'k')]"
]
},
- "execution_count": 841,
+ "execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 842,
+ "execution_count": 44,
"metadata": {
"collapsed": false
},
"62"
]
},
- "execution_count": 842,
+ "execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 843,
+ "execution_count": 45,
"metadata": {
"collapsed": false,
"scrolled": true
" ('y', 'n', 'c')]"
]
},
- "execution_count": 843,
+ "execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 858,
+ "execution_count": 46,
"metadata": {
"collapsed": false
},
" ('y', 'n', 'c')]"
]
},
- "execution_count": 858,
+ "execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 844,
+ "execution_count": 47,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 845,
+ "execution_count": 48,
"metadata": {
"collapsed": false
},
"13"
]
},
- "execution_count": 845,
+ "execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 846,
+ "execution_count": 49,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 847,
+ "execution_count": 50,
"metadata": {
"collapsed": false
},
"Signal(bank='e', wire='e')"
]
},
- "execution_count": 847,
+ "execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 848,
+ "execution_count": 51,
"metadata": {
"collapsed": false
},
"True"
]
},
- "execution_count": 848,
+ "execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 849,
+ "execution_count": 52,
"metadata": {
"collapsed": false
},
"True"
]
},
- "execution_count": 849,
+ "execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 850,
+ "execution_count": 53,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 851,
+ "execution_count": 54,
"metadata": {
"collapsed": false
},
},
{
"cell_type": "code",
- "execution_count": 852,
+ "execution_count": 55,
"metadata": {
"collapsed": false
},
{
"data": {
"text/plain": [
- "{frozenset({'e', 'y'}),\n",
+ "{frozenset({'b', 'g'}),\n",
+ " frozenset({'e', 'y'}),\n",
" frozenset({'t', 'x'}),\n",
- " frozenset({'i', 'n'}),\n",
" frozenset({'m'}),\n",
- " frozenset({'b', 'g'}),\n",
+ " frozenset({'i', 'n'}),\n",
" frozenset({'f', 'p'})}"
]
},
- "execution_count": 852,
+ "execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 853,
+ "execution_count": 56,
"metadata": {
"collapsed": false
},
"True"
]
},
- "execution_count": 853,
+ "execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 854,
+ "execution_count": 57,
"metadata": {
"collapsed": false
},
" frozenset({2, 3}))"
]
},
- "execution_count": 854,
+ "execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 855,
+ "execution_count": 58,
"metadata": {
"collapsed": false
},
"False"
]
},
- "execution_count": 855,
+ "execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 856,
+ "execution_count": 59,
"metadata": {
"collapsed": false
},
"False"
]
},
- "execution_count": 856,
+ "execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
--- /dev/null
+import string
+import collections
+import multiprocessing
+import itertools
+from enigma import *
+
+
+Signal = collections.namedtuple('Signal', ['bank', 'wire'])
+Connection = collections.namedtuple('Connection', ['banks', 'scrambler'])
+MenuItem = collections.namedtuple('MenuIem', ['before', 'after', 'number'])
+
+
+class Scrambler(object):
+ def __init__(self, wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec,
+ wheel1_pos='a', wheel2_pos='a', wheel3_pos='a'):
+ self.wheel1 = SimpleWheel(wheel1_spec, position=wheel1_pos)
+ self.wheel2 = SimpleWheel(wheel2_spec, position=wheel2_pos)
+ self.wheel3 = SimpleWheel(wheel3_spec, position=wheel3_pos)
+ self.reflector = Reflector(reflector_spec)
+
+ def __getattribute__(self, name):
+ if name=='wheel_positions':
+ return self.wheel1.position, self.wheel2.position, self.wheel3.position
+ elif name=='wheel_positions_l':
+ return self.wheel1.position_l, self.wheel2.position_l, self.wheel3.position_l
+ else:
+ return object.__getattribute__(self, name)
+
+ def advance(self, wheel1=False, wheel2=False, wheel3=True):
+ if wheel1: self.wheel1.advance()
+ if wheel2: self.wheel2.advance()
+ if wheel3: self.wheel3.advance()
+
+ def lookup(self, letter):
+ a = self.wheel3.forward(letter)
+ b = self.wheel2.forward(a)
+ c = self.wheel1.forward(b)
+ d = self.reflector.forward(c)
+ e = self.wheel1.backward(d)
+ f = self.wheel2.backward(e)
+ g = self.wheel3.backward(f)
+ return g
+
+ def set_positions(self, wheel1_pos, wheel2_pos, wheel3_pos):
+ self.wheel1.set_position(wheel1_pos)
+ self.wheel2.set_position(wheel2_pos)
+ self.wheel3.set_position(wheel3_pos)
+
+
+class Bombe(object):
+
+ def __init__(self, wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec,
+ menu=None, start_signal=None, use_diagonal_board=True,
+ verify_plugboard=True):
+ self.connections = []
+ self.wheel1_spec = wheel1_spec
+ self.wheel2_spec = wheel2_spec
+ self.wheel3_spec = wheel3_spec
+ self.reflector_spec = reflector_spec
+ if menu:
+ self.read_menu(menu)
+ if start_signal:
+ self.test_start = start_signal
+ self.use_diagonal_board = use_diagonal_board
+ self.verify_plugboard = verify_plugboard
+
+ def __getattribute__(self, name):
+ if name=='wheel_positions':
+ return self.connections[0].scrambler.wheel_positions
+ elif name=='wheel_positions_l':
+ return self.connections[0].scrambler.wheel_positions_l
+ else:
+ return object.__getattribute__(self, name)
+
+ def __call__(self, start_positions):
+ return start_positions, self.test(initial_signal=self.test_start,
+ start_positions=start_positions,
+ use_diagonal_board=self.use_diagonal_board,
+ verify_plugboard=self.verify_plugboard)
+
+ def add_connection(self, bank_before, bank_after, scrambler):
+ self.connections += [Connection([bank_before, bank_after], scrambler)]
+
+ def read_menu(self, menu):
+ for item in menu:
+ scrambler = Scrambler(self.wheel1_spec, self.wheel2_spec, self.wheel3_spec,
+ self.reflector_spec,
+ wheel3_pos=unpos(item.number - 1))
+ self.add_connection(item.before, item.after, scrambler)
+ most_common_letter = (collections.Counter(m.before for m in menu) + collections.Counter(m.after for m in menu)).most_common(1)[0][0]
+ self.test_start = Signal(most_common_letter, most_common_letter)
+
+ def set_positions(self, wheel1_pos, wheel2_pos, wheel3_pos):
+ for i, c in enumerate(self.connections):
+ c.scrambler.set_positions(wheel1_pos, wheel2_pos, unpos(pos(wheel3_pos) + i))
+
+ def test(self, initial_signal=None, start_positions=None, use_diagonal_board=True,
+ verify_plugboard=True):
+ self.banks = {label:
+ dict(zip(string.ascii_lowercase, [False]*len(string.ascii_lowercase)))
+ for label in string.ascii_lowercase}
+ if start_positions:
+ self.set_positions(*start_positions)
+ if not initial_signal:
+ initial_signal = self.test_start
+ self.pending = [initial_signal]
+ self.propagate(use_diagonal_board)
+ live_wire_count = len([self.banks[self.test_start.bank][w]
+ for w in self.banks[self.test_start.bank]
+ if self.banks[self.test_start.bank][w]])
+ if live_wire_count < 26:
+ if verify_plugboard:
+ possibles = self.possible_plugboards()
+ return all(s0.isdisjoint(s1) for s0 in possibles for s1 in possibles if s0 != s1)
+ else:
+ return True
+ else:
+ return False
+
+ def propagate(self, use_diagonal_board):
+ while self.pending:
+ current = self.pending[0]
+ # print("processing", current)
+ self.pending = self.pending[1:]
+ if not self.banks[current.bank][current.wire]:
+ self.banks[current.bank][current.wire] = True
+ if use_diagonal_board:
+ self.pending += [Signal(current.wire, current.bank)]
+ for c in self.connections:
+ if current.bank in c.banks:
+ other_bank = [b for b in c.banks if b != current.bank][0]
+ other_wire = c.scrambler.lookup(current.wire)
+ # print(" adding", other_bank, other_wire, "because", c.banks)
+ self.pending += [Signal(other_bank, other_wire)]
+
+ def run(self, run_start=None, wheel1_pos='a', wheel2_pos='a', wheel3_pos='a', use_diagonal_board=True):
+ if not run_start:
+ run_start = self.test_start
+ self.solutions = []
+ self.set_positions(wheel1_pos, wheel2_pos, wheel3_pos)
+ for run_index in range(26*26*26):
+ if self.test(initial_signal=run_start, use_diagonal_board=use_diagonal_board):
+ self.solutions += [self.connections[0].scrambler.wheel_positions_l]
+ advance3 = True
+ advance2 = False
+ advance1 = False
+ if (run_index + 1) % 26 == 0: advance2 = True
+ if (run_index + 1) % (26*26) == 0: advance1 = True
+ for c in self.connections:
+ c.scrambler.advance(advance1, advance2, advance3)
+ return self.solutions
+
+ def possible_plugboards(self):
+ possibles = set()
+ for b in self.banks:
+ active = [w for w in self.banks[b] if self.banks[b][w]]
+ inactive = [w for w in self.banks[b] if not self.banks[b][w]]
+ if len(active) == 1:
+ possibles = possibles.union({frozenset((b, active[0]))})
+ if len(inactive) == 1:
+ possibles = possibles.union({frozenset((b, inactive[0]))})
+ return possibles
+
"""A generic substitution cipher, that has different transforms in the
forward and backward directions. It requires that the transforms for all
letters by provided.
-
- >>> lt = LetterTransformer([('z', 'a')] + [(l, string.ascii_lowercase[i+1]) \
- for i, l in enumerate(string.ascii_lowercase[:-1])], \
- raw_transform = True)
- >>> 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]
- >>> 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]
-
- >>> lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))
- >>> 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]
- >>> 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]
- >>> cat(lt.forward(l) for l in string.ascii_lowercase)
- 'zyxwcabdefghijklmnopqrstuv'
- >>> cat(lt.backward(l) for l in string.ascii_lowercase)
- 'fgehijklmnopqrstuvwxyzdcba'
"""
def __init__(self, specification, raw_transform=False):
if raw_transform:
"""A plugboard, a type of letter transformer where forward and backward
transforms are the same. If a letter isn't explicitly transformed, it is
kept as it is.
-
- >>> pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper())
- >>> 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]
- >>> pb.forward_map == pb.backward_map
- True
- >>> cat(pb.forward(l) for l in string.ascii_lowercase)
- 'ugcdypblnzkhmisfrqoxavwtej'
- >>> cat(pb.backward(l) for l in string.ascii_lowercase)
- 'ugcdypblnzkhmisfrqoxavwtej'
"""
def parse_specification(self, specification):
return [tuple(clean(p)) for p in specification.split()]
class Reflector(Plugboard):
"""A reflector is a plugboard that requires 13 transforms.
-
- >>> reflector_b = Reflector(reflector_b_spec)
- >>> reflector_b.forward_map == reflector_b.backward_map
- True
- >>> 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]
- >>> cat(reflector_b.forward(l) for l in string.ascii_lowercase)
- 'yruhqsldpxngokmiebfzcwvjat'
- >>> cat(reflector_b.backward(l) for l in string.ascii_lowercase)
- 'yruhqsldpxngokmiebfzcwvjat'
"""
def validate_transform(self, transform):
if len(transform) != 13:
Letter inputs and outputs are given relative to the frame holding the wheel,
so if the wheel is advanced three places, an input of 'p' will enter the
wheel on the position under the wheel's 'q' label.
-
- >>> rotor_1_transform = list(zip(string.ascii_lowercase, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))
- >>> wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True)
- >>> cat(wheel_1.forward(l) for l in string.ascii_lowercase)
- 'ekmflgdqvzntowyhxuspaibrcj'
- >>> cat(wheel_1.backward(l) for l in string.ascii_lowercase)
- 'uwygadfpvzbeckmthxslrinqoj'
-
-
- >>> wheel_2 = SimpleWheel(wheel_ii_spec)
- >>> cat(wheel_2.forward(l) for l in string.ascii_lowercase)
- 'ajdksiruxblhwtmcqgznpyfvoe'
- >>> cat(wheel_2.backward(l) for l in string.ascii_lowercase)
- 'ajpczwrlfbdkotyuqgenhxmivs'
-
- >>> wheel_3 = SimpleWheel(wheel_iii_spec)
- >>> wheel_3.set_position('a')
- >>> wheel_3.advance()
- >>> cat(wheel_3.forward(l) for l in string.ascii_lowercase)
- 'cegikboqswuymxdhvfzjltrpna'
- >>> cat(wheel_3.backward(l) for l in string.ascii_lowercase)
- 'zfaobrcpdteumygxhwivkqjnls'
- >>> wheel_3.position
- 1
- >>> wheel_3.position_l
- 'b'
-
- >>> for _ in range(24): wheel_3.advance()
- >>> wheel_3.position
- 25
- >>> wheel_3.position_l
- 'z'
- >>> cat(wheel_3.forward(l) for l in string.ascii_lowercase)
- 'pcegikmdqsuywaozfjxhblnvtr'
- >>> cat(wheel_3.backward(l) for l in string.ascii_lowercase)
- 'nubhcqdterfvgwoaizjykxmslp'
-
- >>> wheel_3.advance()
- >>> wheel_3.position
- 0
- >>> wheel_3.position_l
- 'a'
- >>> cat(wheel_3.forward(l) for l in string.ascii_lowercase)
- 'bdfhjlcprtxvznyeiwgakmusqo'
- >>> cat(wheel_3.backward(l) for l in string.ascii_lowercase)
- 'tagbpcsdqeufvnzhyixjwlrkom'
"""
def __init__(self, transform, position='a', raw_transform=False):
super(SimpleWheel, self).__init__(transform, raw_transform)
The peg_positions are the number of advances of this wheel before it will
advance the next wheel.
- >>> wheel_3 = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', ring_setting=1)
- >>> wheel_3.position
- 1
- >>> wheel_3.peg_positions
- [20]
- >>> wheel_3.position_l
- 'b'
- >>> wheel_3.advance()
- >>> wheel_3.position
- 2
- >>> wheel_3.peg_positions
- [19]
- >>> wheel_3.position_l
- 'c'
-
- >>> wheel_6 = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', ring_setting=3)
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'xkqhwpvngzrcfoiaselbtymjdu'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'ptlyrmidoxbswhnfckquzgeavj'
- >>> wheel_6.position
- 25
- >>> 11 in wheel_6.peg_positions
- True
- >>> 24 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'b'
-
- >>> wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'jpgvoumfyqbenhzrdkasxlictw'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'skxqlhcnwarvgmebjptyfdzuio'
- >>> wheel_6.position
- 0
- >>> 10 in wheel_6.peg_positions
- True
- >>> 23 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'c'
-
- >>> for _ in range(22): wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'mgxantkzsyqjcufirldvhoewbp'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'dymswobuplgraevzkqifntxcjh'
- >>> wheel_6.position
- 22
- >>> 1 in wheel_6.peg_positions
- True
- >>> 14 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'y'
-
- >>> wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'fwzmsjyrxpibtehqkcugndvaol'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'xlrvnatokfqzduyjphemswbigc'
- >>> wheel_6.position
- 23
- >>> 0 in wheel_6.peg_positions
- True
- >>> 13 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'z'
-
- >>> wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'vylrixqwohasdgpjbtfmcuznke'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'kqumzsnjepyctxiogdlrvahfbw'
- >>> wheel_6.position
- 24
- >>> 25 in wheel_6.peg_positions
- True
- >>> 12 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'a'
-
- >>> wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'xkqhwpvngzrcfoiaselbtymjdu'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'ptlyrmidoxbswhnfckquzgeavj'
- >>> wheel_6.position
- 25
- >>> 24 in wheel_6.peg_positions
- True
- >>> 11 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'b'
-
- >>> wheel_6.advance()
- >>> cat(wheel_6.forward(l) for l in string.ascii_lowercase)
- 'jpgvoumfyqbenhzrdkasxlictw'
- >>> cat(wheel_6.backward(l) for l in string.ascii_lowercase)
- 'skxqlhcnwarvgmebjptyfdzuio'
- >>> wheel_6.position
- 0
- >>> 23 in wheel_6.peg_positions
- True
- >>> 10 in wheel_6.peg_positions
- True
- >>> wheel_6.position_l
- 'c'
-
"""
def __init__(self, transform, ring_peg_letters, ring_setting=1, position='a', raw_transform=False):
self.ring_peg_letters = ring_peg_letters
class Enigma(object):
"""An Enigma machine.
- >>> enigma = Enigma(reflector_b_spec, \
- wheel_i_spec, wheel_i_pegs, \
- wheel_ii_spec, wheel_ii_pegs, \
- wheel_iii_spec, wheel_iii_pegs, \
- 1, 1, 1, \
- '')
- >>> enigma.set_wheels('a', 'a', 't')
- >>> enigma.wheel_positions
- (0, 0, 19)
- >>> cat(enigma.wheel_positions_l)
- 'aat'
- >>> enigma.peg_positions
- ([16], [4], [2])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'puvioztjdhxmlyeawsrgbcqknf'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 0, 20)
- >>> cat(enigma.wheel_positions_l)
- 'aau'
- >>> enigma.peg_positions
- ([16], [4], [1])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'baigpldqcowfyzjehvtsxrkumn'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 0, 21)
- >>> cat(enigma.wheel_positions_l)
- 'aav'
- >>> enigma.peg_positions
- ([16], [4], [0])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'mnvfydiwgzsoablrxpkutchqej'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 1, 22)
- >>> cat(enigma.wheel_positions_l)
- 'abw'
- >>> enigma.peg_positions
- ([16], [3], [25])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'ulfopcykswhbzvderqixanjtgm'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 1, 23)
- >>> cat(enigma.wheel_positions_l)
- 'abx'
- >>> enigma.peg_positions
- ([16], [3], [24])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'qmwftdyovursbzhxaklejicpgn'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 1, 24)
- >>> cat(enigma.wheel_positions_l)
- 'aby'
- >>> enigma.peg_positions
- ([16], [3], [23])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'oljmzxrvucybdqasngpwihtfke'
-
-
-
-
- >>> enigma.set_wheels('a', 'd', 't')
- >>> enigma.wheel_positions
- (0, 3, 19)
- >>> cat(enigma.wheel_positions_l)
- 'adt'
- >>> enigma.peg_positions
- ([16], [1], [2])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'zcbpqxwsjiuonmldethrkygfva'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 3, 20)
- >>> cat(enigma.wheel_positions_l)
- 'adu'
- >>> enigma.peg_positions
- ([16], [1], [1])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'ehprawjbngotxikcsdqlzyfmvu'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 3, 21)
- >>> cat(enigma.wheel_positions_l)
- 'adv'
- >>> enigma.peg_positions
- ([16], [1], [0])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'eqzxarpihmnvjkwgbfuyslodtc'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (0, 4, 22)
- >>> cat(enigma.wheel_positions_l)
- 'aew'
- >>> enigma.peg_positions
- ([16], [0], [25])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'qedcbtpluzmhkongavwfirsyxj'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (1, 5, 23)
- >>> cat(enigma.wheel_positions_l)
- 'bfx'
- >>> enigma.peg_positions
- ([15], [25], [24])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'iwuedhsfazqxytvrkpgncoblmj'
-
- >>> enigma.advance()
- >>> enigma.wheel_positions
- (1, 5, 24)
- >>> cat(enigma.wheel_positions_l)
- 'bfy'
- >>> enigma.peg_positions
- ([15], [25], [23])
- >>> cat(enigma.lookup(l) for l in string.ascii_lowercase)
- 'baknstqzrmcxjdvygiefwoulph'
-
-
- >>> enigma.set_wheels('a', 'a', 'a')
- >>> ct = enigma.encipher('testmessage')
- >>> ct
- 'olpfhnvflyn'
-
- >>> enigma.set_wheels('a', 'd', 't')
- >>> ct = enigma.encipher('testmessage')
- >>> ct
- 'lawnjgpwjik'
-
-
- >>> enigma.set_wheels('b', 'd', 'q')
- >>> ct = enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
- >>> ct
- 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr'
- >>> enigma.left_wheel.position_l
- 'c'
- >>> enigma.middle_wheel.position_l
- 'h'
- >>> enigma.right_wheel.position_l
- 'a'
-
- # Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm
- # Enigma simulation settings are
- # http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJEU;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX
- >>> enigma31 = Enigma(reflector_b_spec, \
- wheel_i_spec, wheel_i_pegs, \
- wheel_v_spec, wheel_v_pegs, \
- wheel_iii_spec, wheel_iii_pegs, \
- 6, 20, 24, \
- 'ua pf rq so ni ey bg hl tx zj')
-
- >>> enigma31.set_wheels('j', 'e', 'u')
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (4, 11, 24)
- >>> cat(enigma31.wheel_positions_l)
- 'jev'
- >>> enigma31.peg_positions
- ([7], [21], [0])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'mvqjlyowkdieasgzcunxrbhtfp'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (4, 12, 25)
- >>> cat(enigma31.wheel_positions_l)
- 'jfw'
- >>> enigma31.peg_positions
- ([7], [20], [25])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'sjolzuyvrbwdpxcmtiaqfhknge'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (4, 12, 0)
- >>> cat(enigma31.wheel_positions_l)
- 'jfx'
- >>> enigma31.peg_positions
- ([7], [20], [24])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'qrxedkoywufmlvgsabpzjnicht'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (4, 12, 1)
- >>> cat(enigma31.wheel_positions_l)
- 'jfy'
- >>> enigma31.peg_positions
- ([7], [20], [23])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'hpsukliagqefwvtbjxcodnmrzy'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (4, 12, 2)
- >>> cat(enigma31.wheel_positions_l)
- 'jfz'
- >>> enigma31.peg_positions
- ([7], [20], [22])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'zevnbpyqowrtxdifhkulscjmga'
-
-
- >>> enigma31.set_wheels('i', 'd', 'z')
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 3)
- >>> cat(enigma31.wheel_positions_l)
- 'ida'
- >>> enigma31.peg_positions
- ([8], [22], [21])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'ikhpqrvcambzjondefwyxgsutl'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 4)
- >>> cat(enigma31.wheel_positions_l)
- 'idb'
- >>> enigma31.peg_positions
- ([8], [22], [20])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'cdabskhgzwfmlqvunyexpojtri'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 5)
- >>> cat(enigma31.wheel_positions_l)
- 'idc'
- >>> enigma31.peg_positions
- ([8], [22], [19])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'pcbwiqhgemyvjsuaftnroldzkx'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 6)
- >>> cat(enigma31.wheel_positions_l)
- 'idd'
- >>> enigma31.peg_positions
- ([8], [22], [18])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'xcbfvdnouptmlghjzwykierasq'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 7)
- >>> cat(enigma31.wheel_positions_l)
- 'ide'
- >>> enigma31.peg_positions
- ([8], [22], [17])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'xfvglbdynuseriwqpmkzjcoaht'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 8)
- >>> cat(enigma31.wheel_positions_l)
- 'idf'
- >>> enigma31.peg_positions
- ([8], [22], [16])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'tfpqlbouynsewjgcdxkahzmriv'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 9)
- >>> cat(enigma31.wheel_positions_l)
- 'idg'
- >>> enigma31.peg_positions
- ([8], [22], [15])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'cjaunvlwtbygzexrspqidfhokm'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 10)
- >>> cat(enigma31.wheel_positions_l)
- 'idh'
- >>> enigma31.peg_positions
- ([8], [22], [14])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'yltxkrqvowebzpingfucshjdam'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 11)
- >>> cat(enigma31.wheel_positions_l)
- 'idi'
- >>> enigma31.peg_positions
- ([8], [22], [13])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'myktluzrnxceaiqsohpdfwvjbg'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 12)
- >>> cat(enigma31.wheel_positions_l)
- 'idj'
- >>> enigma31.peg_positions
- ([8], [22], [12])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'pynjrmiugdqxfcvakewzhoslbt'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 13)
- >>> cat(enigma31.wheel_positions_l)
- 'idk'
- >>> enigma31.peg_positions
- ([8], [22], [11])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'mwvedyplnoxhaijgrqtszcbkfu'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 14)
- >>> cat(enigma31.wheel_positions_l)
- 'idl'
- >>> enigma31.peg_positions
- ([8], [22], [10])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'qcbrfeutvoxpnmjladzhgiykws'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 15)
- >>> cat(enigma31.wheel_positions_l)
- 'idm'
- >>> enigma31.peg_positions
- ([8], [22], [9])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'dnoahryetsmukbcvwfjilpqzgx'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 16)
- >>> cat(enigma31.wheel_positions_l)
- 'idn'
- >>> enigma31.peg_positions
- ([8], [22], [8])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'nidcfehgbqsovalyjzkxwmutpr'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 17)
- >>> cat(enigma31.wheel_positions_l)
- 'ido'
- >>> enigma31.peg_positions
- ([8], [22], [7])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'joifxdulcarhzpbntkwqgysevm'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 18)
- >>> cat(enigma31.wheel_positions_l)
- 'idp'
- >>> enigma31.peg_positions
- ([8], [22], [6])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'ptnlsxvozmwdjchayuebrgkfqi'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 19)
- >>> cat(enigma31.wheel_positions_l)
- 'idq'
- >>> enigma31.peg_positions
- ([8], [22], [5])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'slwopzqnmxybihdeguavrtcjkf'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 20)
- >>> cat(enigma31.wheel_positions_l)
- 'idr'
- >>> enigma31.peg_positions
- ([8], [22], [4])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'hcbedwlamzogixkytsrqvufnpj'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 21)
- >>> cat(enigma31.wheel_positions_l)
- 'ids'
- >>> enigma31.peg_positions
- ([8], [22], [3])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'odxbjwzrmelkisavuhnyqpfctg'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 22)
- >>> cat(enigma31.wheel_positions_l)
- 'idt'
- >>> enigma31.peg_positions
- ([8], [22], [2])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'udgbfeclrwnhxksvtioqapjmzy'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 23)
- >>> cat(enigma31.wheel_positions_l)
- 'idu'
- >>> enigma31.peg_positions
- ([8], [22], [1])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'nrdczqxmowvshaiufblypkjgte'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 10, 24)
- >>> cat(enigma31.wheel_positions_l)
- 'idv'
- >>> enigma31.peg_positions
- ([8], [22], [0])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'hkifjdoacebqtzgulyvmpsxwrn'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 11, 25)
- >>> cat(enigma31.wheel_positions_l)
- 'iew'
- >>> enigma31.peg_positions
- ([8], [21], [25])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'yptzuhofqvnmlkgbixwcejsrad'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 11, 0)
- >>> cat(enigma31.wheel_positions_l)
- 'iex'
- >>> enigma31.peg_positions
- ([8], [21], [24])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'vkdcwhqfjibzsptngumoraeyxl'
-
- >>> enigma31.advance()
- >>> enigma31.wheel_positions
- (3, 11, 1)
- >>> cat(enigma31.wheel_positions_l)
- 'iey'
- >>> enigma31.peg_positions
- ([8], [21], [23])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'wenpbqrouxlkychdfgzvitajms'
-
-
- >>> enigma31.set_wheels('i', 'z', 'd')
- >>> enigma31.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')
- 'apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki'
- >>> enigma31.wheel_positions
- (4, 9, 10)
- >>> cat(enigma31.wheel_positions_l)
- 'jch'
- >>> enigma31.peg_positions
- ([7], [23], [14])
- >>> cat(enigma31.lookup(l) for l in string.ascii_lowercase)
- 'mopnigfuesqwadbcktjrhylzvx'
- >>> enigma31.set_wheels('i', 'z', 'd')
- >>> enigma31.decipher('apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki')
- 'verylongtestmessagewithanextrabitofmessageforgoodmeasure'
"""
def __init__(self, reflector_spec,
left_wheel_spec, left_wheel_pegs,
--- /dev/null
+import unittest
+import collections
+
+from enigma import *
+
+class LetterTransformerTest(unittest.TestCase):
+
+ def test_maps1(self):
+ lt = LetterTransformer([('z', 'a')] + \
+ list(zip(string.ascii_lowercase, string.ascii_lowercase[1:])),
+ raw_transform = True)
+ self.assertEqual(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])
+ self.assertEqual(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])
+
+
+ def test_maps2(self):
+ lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))
+ self.assertEqual(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])
+ self.assertEqual(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])
+
+ def test_transform(self):
+ lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))
+ self.assertEqual(cat(lt.forward(l) for l in string.ascii_lowercase),
+ 'zyxwcabdefghijklmnopqrstuv')
+ self.assertEqual(cat(lt.backward(l) for l in string.ascii_lowercase),
+ 'fgehijklmnopqrstuvwxyzdcba')
+
+
+class PlugboardTest(unittest.TestCase):
+ def setUp(self):
+ self.pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper())
+
+ def test_maps(self):
+ self.assertEqual(self.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])
+ self.assertEqual(self.pb.forward_map, self.pb.backward_map)
+
+ def test_transform(self):
+ self.assertEqual(cat(self.pb.forward(l)
+ for l in string.ascii_lowercase),
+ 'ugcdypblnzkhmisfrqoxavwtej')
+ self.assertEqual(cat(self.pb.backward(l)
+ for l in string.ascii_lowercase),
+ 'ugcdypblnzkhmisfrqoxavwtej')
+
+
+class ReflectorTest(unittest.TestCase):
+ def setUp(self):
+ self.ref = Reflector(reflector_b_spec)
+
+ def test_maps(self):
+ self.assertEqual(self.ref.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])
+ self.assertEqual(self.ref.forward_map, self.ref.backward_map)
+
+ def test_transform(self):
+ self.assertEqual(cat(self.ref.forward(l)
+ for l in string.ascii_lowercase),
+ 'yruhqsldpxngokmiebfzcwvjat')
+ self.assertEqual(cat(self.ref.backward(l)
+ for l in string.ascii_lowercase),
+ 'yruhqsldpxngokmiebfzcwvjat')
+
+
+class SimpleWheelTest(unittest.TestCase):
+ def test_init1(self):
+ rotor_1_transform = list(zip(string.ascii_lowercase,
+ 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))
+ wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True)
+ self.assertEqual(cat(wheel_1.forward(l)
+ for l in string.ascii_lowercase),
+ 'ekmflgdqvzntowyhxuspaibrcj')
+ self.assertEqual(cat(wheel_1.backward(l)
+ for l in string.ascii_lowercase),
+ 'uwygadfpvzbeckmthxslrinqoj')
+
+ def test_init2(self):
+ wheel_2 = SimpleWheel(wheel_ii_spec)
+ self.assertEqual(cat(wheel_2.forward(l)
+ for l in string.ascii_lowercase),
+ 'ajdksiruxblhwtmcqgznpyfvoe')
+ self.assertEqual(cat(wheel_2.backward(l)
+ for l in string.ascii_lowercase),
+ 'ajpczwrlfbdkotyuqgenhxmivs')
+
+ def test_advance(self):
+ wheel_3 = SimpleWheel(wheel_iii_spec)
+ wheel_3.set_position('a')
+ wheel_3.advance()
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'cegikboqswuymxdhvfzjltrpna')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'zfaobrcpdteumygxhwivkqjnls')
+ self.assertEqual(wheel_3.position, 1)
+ self.assertEqual(wheel_3.position_l, 'b')
+
+ for _ in range(24): wheel_3.advance()
+
+ self.assertEqual(wheel_3.position, 25)
+ self.assertEqual(wheel_3.position_l, 'z')
+
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'pcegikmdqsuywaozfjxhblnvtr')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'nubhcqdterfvgwoaizjykxmslp')
+
+ wheel_3.advance()
+ self.assertEqual(wheel_3.position, 0)
+ self.assertEqual(wheel_3.position_l, 'a')
+
+
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'bdfhjlcprtxvznyeiwgakmusqo')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'tagbpcsdqeufvnzhyixjwlrkom')
+
+
+class SimpleWheelTest(unittest.TestCase):
+ def test_init1(self):
+ wheel = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b',
+ ring_setting=1)
+ self.assertEqual(wheel.position, 1)
+ self.assertEqual(wheel.peg_positions, [20])
+ self.assertEqual(wheel.position_l, 'b')
+
+ wheel.advance()
+ self.assertEqual(wheel.position, 2)
+ self.assertEqual(wheel.peg_positions, [19])
+ self.assertEqual(wheel.position_l, 'c')
+
+ def test_init2(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ self.assertEqual(wheel.position, 25)
+ self.assertIn(11, wheel.peg_positions)
+ self.assertIn(24, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'b')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'xkqhwpvngzrcfoiaselbtymjdu')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'ptlyrmidoxbswhnfckquzgeavj')
+
+
+ def test_advance(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 0)
+ self.assertIn(10, wheel.peg_positions)
+ self.assertIn(23, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'c')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'jpgvoumfyqbenhzrdkasxlictw')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'skxqlhcnwarvgmebjptyfdzuio')
+
+ def test_advance_23(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(23):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 22)
+ self.assertIn(1, wheel.peg_positions)
+ self.assertIn(14, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'y')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'mgxantkzsyqjcufirldvhoewbp')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'dymswobuplgraevzkqifntxcjh')
+
+ def test_advance_24(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(24):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 23)
+ self.assertIn(0, wheel.peg_positions)
+ self.assertIn(13, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'z')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'fwzmsjyrxpibtehqkcugndvaol')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'xlrvnatokfqzduyjphemswbigc')
+
+ def test_advance_25(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(25):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 24)
+ self.assertIn(25, wheel.peg_positions)
+ self.assertIn(12, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'a')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'vylrixqwohasdgpjbtfmcuznke')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'kqumzsnjepyctxiogdlrvahfbw')
+
+ def test_advance_26(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(26):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 25)
+ self.assertIn(24, wheel.peg_positions)
+ self.assertIn(11, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'b')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'xkqhwpvngzrcfoiaselbtymjdu')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'ptlyrmidoxbswhnfckquzgeavj')
+
+
+ def test_advance_27(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(27):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 0)
+ self.assertIn(23, wheel.peg_positions)
+ self.assertIn(10, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'c')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'jpgvoumfyqbenhzrdkasxlictw')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'skxqlhcnwarvgmebjptyfdzuio')
+
+class EnigmaTest(unittest.TestCase):
+
+ def setUp(self):
+ self.enigma = Enigma(reflector_b_spec,
+ wheel_i_spec, wheel_i_pegs,
+ wheel_ii_spec, wheel_ii_pegs,
+ wheel_iii_spec, wheel_iii_pegs,
+ 1, 1, 1,
+ '')
+
+ # Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm
+ # Enigma simulation settings are
+ # http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJEU;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX
+ self.enigma31 = Enigma(reflector_b_spec,
+ wheel_i_spec, wheel_i_pegs,
+ wheel_v_spec, wheel_v_pegs,
+ wheel_iii_spec, wheel_iii_pegs,
+ 6, 20, 24,
+ 'ua pf rq so ni ey bg hl tx zj')
+
+
+ def test_middle_advance(self):
+ self.enigma.set_wheels('a', 'a', 't')
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 19))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aat')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [2]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'puvioztjdhxmlyeawsrgbcqknf')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 20))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aau')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [1]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'baigpldqcowfyzjehvtsxrkumn')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 21))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aav')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [0]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'mnvfydiwgzsoablrxpkutchqej')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 22))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'abw')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [25]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'ulfopcykswhbzvderqixanjtgm')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 23))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'abx')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [24]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'qmwftdyovursbzhxaklejicpgn')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 24))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aby')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [23]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'oljmzxrvucybdqasngpwihtfke')
+
+
+ def test_double_advance(self):
+ self.enigma.set_wheels('a', 'd', 't')
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 19))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adt')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [2]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'zcbpqxwsjiuonmldethrkygfva')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 20))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adu')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [1]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'ehprawjbngotxikcsdqlzyfmvu')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 21))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adv')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [0]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'eqzxarpihmnvjkwgbfuyslodtc')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 4, 22))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aew')
+ self.assertEqual(self.enigma.peg_positions, ([16], [0], [25]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'qedcbtpluzmhkongavwfirsyxj')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (1, 5, 23))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfx')
+ self.assertEqual(self.enigma.peg_positions, ([15], [25], [24]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'iwuedhsfazqxytvrkpgncoblmj')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (1, 5, 24))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfy')
+ self.assertEqual(self.enigma.peg_positions, ([15], [25], [23]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'baknstqzrmcxjdvygiefwoulph')
+
+
+ def test_simple_encipher(self):
+ self.enigma.set_wheels('a', 'a', 'a')
+ ct = self.enigma.encipher('testmessage')
+ self.assertEqual(ct, 'olpfhnvflyn')
+
+ self.enigma.set_wheels('a', 'd', 't')
+ ct = self.enigma.encipher('testmessage')
+ self.assertEqual(ct, 'lawnjgpwjik')
+
+ self.enigma.set_wheels('b', 'd', 'q')
+ ct = self.enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
+ self.assertEqual(ct,
+ 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr')
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'cha')
+
+
+ def test_advance_with_ring_settings(self):
+ self.enigma31.set_wheels('j', 'e', 'u')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 11, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jev')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [21], [0]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mvqjlyowkdieasgzcunxrbhtfp')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfw')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [25]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'sjolzuyvrbwdpxcmtiaqfhknge')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfx')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [24]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'qrxedkoywufmlvgsabpzjnicht')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfy')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [23]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hpsukliagqefwvtbjxcodnmrzy')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 2))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfz')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [22]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'zevnbpyqowrtxdifhkulscjmga')
+
+
+ def test_advance_with_ring_settings_2(self):
+ self.enigma31.set_wheels('i', 'd', 'z')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 3))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ida')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [21]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'ikhpqrvcambzjondefwyxgsutl')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 4))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idb')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [20]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'cdabskhgzwfmlqvunyexpojtri')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 5))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idc')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [19]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'pcbwiqhgemyvjsuaftnroldzkx')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 6))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idd')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [18]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'xcbfvdnouptmlghjzwykierasq')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 7))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ide')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [17]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'xfvglbdynuseriwqpmkzjcoaht')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 8))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idf')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [16]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'tfpqlbouynsewjgcdxkahzmriv')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 9))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idg')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [15]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'cjaunvlwtbygzexrspqidfhokm')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 10))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idh')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [14]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'yltxkrqvowebzpingfucshjdam')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 11))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idi')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [13]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'myktluzrnxceaiqsohpdfwvjbg')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 12))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idj')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [12]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'pynjrmiugdqxfcvakewzhoslbt')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 13))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idk')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [11]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mwvedyplnoxhaijgrqtszcbkfu')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 14))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idl')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [10]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'qcbrfeutvoxpnmjladzhgiykws')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 15))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idm')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [9]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'dnoahryetsmukbcvwfjilpqzgx')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 16))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idn')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [8]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'nidcfehgbqsovalyjzkxwmutpr')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 17))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ido')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [7]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'joifxdulcarhzpbntkwqgysevm')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 18))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idp')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [6]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'ptnlsxvozmwdjchayuebrgkfqi')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 19))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idq')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [5]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'slwopzqnmxybihdeguavrtcjkf')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 20))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idr')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [4]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hcbedwlamzogixkytsrqvufnpj')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 21))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ids')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [3]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'odxbjwzrmelkisavuhnyqpfctg')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idt')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [2]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'udgbfeclrwnhxksvtioqapjmzy')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idu')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [1]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'nrdczqxmowvshaiufblypkjgte')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idv')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [0]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hkifjdoacebqtzgulyvmpsxwrn')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iew')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [25]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'yptzuhofqvnmlkgbixwcejsrad')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iex')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [24]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'vkdcwhqfjibzsptngumoraeyxl')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iey')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [23]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'wenpbqrouxlkychdfgzvitajms')
+
+ def test_double_advance_with_ring_settings_2(self):
+ self.enigma31.set_wheels('a', 'y', 't')
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayt')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [2]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayu')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [1]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayv')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [0]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 6, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azw')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [0], [25]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bax')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [24]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bay')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [23]))
+
+ self.enigma31.set_wheels('a', 'z', 't')
+ self.assertEqual(self.enigma31.wheel_positions, (21, 6, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azt')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [0], [2]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bau')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [1]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bav')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [0]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbw')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [25]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbx')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [24]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bby')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [23]))
+
+
+ def test_encipher_with_ring(self):
+
+ self.enigma31.set_wheels('i', 'z', 'd')
+ ct = self.enigma31.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')
+ self.assertEqual(ct,
+ 'apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki')
+ self.assertEqual(self.enigma31.wheel_positions, (4, 9, 10))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jch')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [23], [14]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mopnigfuesqwadbcktjrhylzvx')
+
+ self.enigma31.set_wheels('i', 'z', 'd')
+ pt = self.enigma31.decipher('apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki')
+ self.assertEqual(pt,
+ 'verylongtestmessagewithanextrabitofmessageforgoodmeasure')
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
--- /dev/null
+import unittest
+import collections
+
+from enigma import *
+
+class LetterTransformerTest(unittest.TestCase):
+
+ def test_maps1(self):
+ lt = LetterTransformer([('z', 'a')] + \
+ list(zip(string.ascii_lowercase, string.ascii_lowercase[1:])),
+ raw_transform = True)
+ self.assertEqual(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])
+ self.assertEqual(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])
+
+
+ def test_maps2(self):
+ lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))
+ self.assertEqual(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])
+ self.assertEqual(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])
+
+ def test_transform(self):
+ lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase)))
+ self.assertEqual(cat(lt.forward(l) for l in string.ascii_lowercase),
+ 'zyxwcabdefghijklmnopqrstuv')
+ self.assertEqual(cat(lt.backward(l) for l in string.ascii_lowercase),
+ 'fgehijklmnopqrstuvwxyzdcba')
+
+
+class PlugboardTest(unittest.TestCase):
+ def setUp(self):
+ self.pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper())
+
+ def test_maps(self):
+ self.assertEqual(self.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])
+ self.assertEqual(self.pb.forward_map, self.pb.backward_map)
+
+ def test_transform(self):
+ self.assertEqual(cat(self.pb.forward(l)
+ for l in string.ascii_lowercase),
+ 'ugcdypblnzkhmisfrqoxavwtej')
+ self.assertEqual(cat(self.pb.backward(l)
+ for l in string.ascii_lowercase),
+ 'ugcdypblnzkhmisfrqoxavwtej')
+
+
+class ReflectorTest(unittest.TestCase):
+ def setUp(self):
+ self.ref = Reflector(reflector_b_spec)
+
+ def test_maps(self):
+ self.assertEqual(self.ref.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])
+ self.assertEqual(self.ref.forward_map, self.ref.backward_map)
+
+ def test_transform(self):
+ self.assertEqual(cat(self.ref.forward(l)
+ for l in string.ascii_lowercase),
+ 'yruhqsldpxngokmiebfzcwvjat')
+ self.assertEqual(cat(self.ref.backward(l)
+ for l in string.ascii_lowercase),
+ 'yruhqsldpxngokmiebfzcwvjat')
+
+
+class SimpleWheelTest(unittest.TestCase):
+ def test_init1(self):
+ rotor_1_transform = list(zip(string.ascii_lowercase,
+ 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower()))
+ wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True)
+ self.assertEqual(cat(wheel_1.forward(l)
+ for l in string.ascii_lowercase),
+ 'ekmflgdqvzntowyhxuspaibrcj')
+ self.assertEqual(cat(wheel_1.backward(l)
+ for l in string.ascii_lowercase),
+ 'uwygadfpvzbeckmthxslrinqoj')
+
+ def test_init2(self):
+ wheel_2 = SimpleWheel(wheel_ii_spec)
+ self.assertEqual(cat(wheel_2.forward(l)
+ for l in string.ascii_lowercase),
+ 'ajdksiruxblhwtmcqgznpyfvoe')
+ self.assertEqual(cat(wheel_2.backward(l)
+ for l in string.ascii_lowercase),
+ 'ajpczwrlfbdkotyuqgenhxmivs')
+
+ def test_advance(self):
+ wheel_3 = SimpleWheel(wheel_iii_spec)
+ wheel_3.set_position('a')
+ wheel_3.advance()
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'cegikboqswuymxdhvfzjltrpna')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'zfaobrcpdteumygxhwivkqjnls')
+ self.assertEqual(wheel_3.position, 1)
+ self.assertEqual(wheel_3.position_l, 'b')
+
+ for _ in range(24): wheel_3.advance()
+
+ self.assertEqual(wheel_3.position, 25)
+ self.assertEqual(wheel_3.position_l, 'z')
+
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'pcegikmdqsuywaozfjxhblnvtr')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'nubhcqdterfvgwoaizjykxmslp')
+
+ wheel_3.advance()
+ self.assertEqual(wheel_3.position, 0)
+ self.assertEqual(wheel_3.position_l, 'a')
+
+
+ self.assertEqual(cat(wheel_3.forward(l)
+ for l in string.ascii_lowercase),
+ 'bdfhjlcprtxvznyeiwgakmusqo')
+ self.assertEqual(cat(wheel_3.backward(l)
+ for l in string.ascii_lowercase),
+ 'tagbpcsdqeufvnzhyixjwlrkom')
+
+
+class SimpleWheelTest(unittest.TestCase):
+ def test_init1(self):
+ wheel = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b',
+ ring_setting=1)
+ self.assertEqual(wheel.position, 1)
+ self.assertEqual(wheel.peg_positions, [20])
+ self.assertEqual(wheel.position_l, 'b')
+
+ wheel.advance()
+ self.assertEqual(wheel.position, 2)
+ self.assertEqual(wheel.peg_positions, [19])
+ self.assertEqual(wheel.position_l, 'c')
+
+ def test_init2(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ self.assertEqual(wheel.position, 25)
+ self.assertIn(11, wheel.peg_positions)
+ self.assertIn(24, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'b')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'xkqhwpvngzrcfoiaselbtymjdu')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'ptlyrmidoxbswhnfckquzgeavj')
+
+
+ def test_advance(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 0)
+ self.assertIn(10, wheel.peg_positions)
+ self.assertIn(23, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'c')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'jpgvoumfyqbenhzrdkasxlictw')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'skxqlhcnwarvgmebjptyfdzuio')
+
+ def test_advance_23(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(23):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 22)
+ self.assertIn(1, wheel.peg_positions)
+ self.assertIn(14, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'y')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'mgxantkzsyqjcufirldvhoewbp')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'dymswobuplgraevzkqifntxcjh')
+
+ def test_advance_24(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(24):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 23)
+ self.assertIn(0, wheel.peg_positions)
+ self.assertIn(13, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'z')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'fwzmsjyrxpibtehqkcugndvaol')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'xlrvnatokfqzduyjphemswbigc')
+
+ def test_advance_25(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(25):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 24)
+ self.assertIn(25, wheel.peg_positions)
+ self.assertIn(12, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'a')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'vylrixqwohasdgpjbtfmcuznke')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'kqumzsnjepyctxiogdlrvahfbw')
+
+ def test_advance_26(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(26):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 25)
+ self.assertIn(24, wheel.peg_positions)
+ self.assertIn(11, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'b')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'xkqhwpvngzrcfoiaselbtymjdu')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'ptlyrmidoxbswhnfckquzgeavj')
+
+
+ def test_advance_27(self):
+ wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b',
+ ring_setting=3)
+ for _ in range(27):
+ wheel.advance()
+
+ self.assertEqual(wheel.position, 0)
+ self.assertIn(23, wheel.peg_positions)
+ self.assertIn(10, wheel.peg_positions)
+ self.assertEqual(wheel.position_l, 'c')
+ self.assertEqual(cat(wheel.forward(l)
+ for l in string.ascii_lowercase),
+ 'jpgvoumfyqbenhzrdkasxlictw')
+ self.assertEqual(cat(wheel.backward(l)
+ for l in string.ascii_lowercase),
+ 'skxqlhcnwarvgmebjptyfdzuio')
+
+class EnigmaTest(unittest.TestCase):
+
+ def setUp(self):
+ self.enigma = Enigma(reflector_b_spec,
+ wheel_i_spec, wheel_i_pegs,
+ wheel_ii_spec, wheel_ii_pegs,
+ wheel_iii_spec, wheel_iii_pegs,
+ 1, 1, 1,
+ '')
+
+ # Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm
+ # Enigma simulation settings are
+ # http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJEU;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX
+ self.enigma31 = Enigma(reflector_b_spec,
+ wheel_i_spec, wheel_i_pegs,
+ wheel_v_spec, wheel_v_pegs,
+ wheel_iii_spec, wheel_iii_pegs,
+ 6, 20, 24,
+ 'ua pf rq so ni ey bg hl tx zj')
+
+
+ def test_middle_advance(self):
+ self.enigma.set_wheels('a', 'a', 't')
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 19))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aat')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [2]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'puvioztjdhxmlyeawsrgbcqknf')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 20))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aau')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [1]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'baigpldqcowfyzjehvtsxrkumn')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 0, 21))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aav')
+ self.assertEqual(self.enigma.peg_positions, ([16], [4], [0]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'mnvfydiwgzsoablrxpkutchqej')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 22))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'abw')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [25]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'ulfopcykswhbzvderqixanjtgm')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 23))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'abx')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [24]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'qmwftdyovursbzhxaklejicpgn')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 1, 24))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aby')
+ self.assertEqual(self.enigma.peg_positions, ([16], [3], [23]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'oljmzxrvucybdqasngpwihtfke')
+
+
+ def test_double_advance(self):
+ self.enigma.set_wheels('a', 'd', 't')
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 19))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adt')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [2]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'zcbpqxwsjiuonmldethrkygfva')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 20))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adu')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [1]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'ehprawjbngotxikcsdqlzyfmvu')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 3, 21))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'adv')
+ self.assertEqual(self.enigma.peg_positions, ([16], [1], [0]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'eqzxarpihmnvjkwgbfuyslodtc')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (0, 4, 22))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'aew')
+ self.assertEqual(self.enigma.peg_positions, ([16], [0], [25]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'qedcbtpluzmhkongavwfirsyxj')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (1, 5, 23))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfx')
+ self.assertEqual(self.enigma.peg_positions, ([15], [25], [24]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'iwuedhsfazqxytvrkpgncoblmj')
+
+ self.enigma.advance()
+ self.assertEqual(self.enigma.wheel_positions, (1, 5, 24))
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfy')
+ self.assertEqual(self.enigma.peg_positions, ([15], [25], [23]))
+ self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase),
+ 'baknstqzrmcxjdvygiefwoulph')
+
+
+ def test_simple_encipher(self):
+ self.enigma.set_wheels('a', 'a', 'a')
+ ct = self.enigma.encipher('testmessage')
+ self.assertEqual(ct, 'olpfhnvflyn')
+
+ self.enigma.set_wheels('a', 'd', 't')
+ ct = self.enigma.encipher('testmessage')
+ self.assertEqual(ct, 'lawnjgpwjik')
+
+ self.enigma.set_wheels('b', 'd', 'q')
+ ct = self.enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
+ self.assertEqual(ct,
+ 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr')
+ self.assertEqual(cat(self.enigma.wheel_positions_l), 'cha')
+
+
+ def test_advance_with_ring_settings(self):
+ self.enigma31.set_wheels('j', 'e', 'u')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 11, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jev')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [21], [0]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mvqjlyowkdieasgzcunxrbhtfp')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfw')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [25]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'sjolzuyvrbwdpxcmtiaqfhknge')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfx')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [24]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'qrxedkoywufmlvgsabpzjnicht')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfy')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [23]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hpsukliagqefwvtbjxcodnmrzy')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (4, 12, 2))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfz')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [20], [22]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'zevnbpyqowrtxdifhkulscjmga')
+
+
+ def test_advance_with_ring_settings_2(self):
+ self.enigma31.set_wheels('i', 'd', 'z')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 3))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ida')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [21]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'ikhpqrvcambzjondefwyxgsutl')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 4))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idb')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [20]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'cdabskhgzwfmlqvunyexpojtri')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 5))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idc')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [19]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'pcbwiqhgemyvjsuaftnroldzkx')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 6))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idd')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [18]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'xcbfvdnouptmlghjzwykierasq')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 7))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ide')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [17]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'xfvglbdynuseriwqpmkzjcoaht')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 8))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idf')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [16]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'tfpqlbouynsewjgcdxkahzmriv')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 9))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idg')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [15]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'cjaunvlwtbygzexrspqidfhokm')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 10))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idh')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [14]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'yltxkrqvowebzpingfucshjdam')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 11))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idi')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [13]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'myktluzrnxceaiqsohpdfwvjbg')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 12))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idj')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [12]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'pynjrmiugdqxfcvakewzhoslbt')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 13))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idk')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [11]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mwvedyplnoxhaijgrqtszcbkfu')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 14))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idl')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [10]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'qcbrfeutvoxpnmjladzhgiykws')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 15))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idm')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [9]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'dnoahryetsmukbcvwfjilpqzgx')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 16))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idn')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [8]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'nidcfehgbqsovalyjzkxwmutpr')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 17))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ido')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [7]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'joifxdulcarhzpbntkwqgysevm')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 18))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idp')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [6]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'ptnlsxvozmwdjchayuebrgkfqi')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 19))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idq')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [5]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'slwopzqnmxybihdeguavrtcjkf')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 20))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idr')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [4]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hcbedwlamzogixkytsrqvufnpj')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 21))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ids')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [3]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'odxbjwzrmelkisavuhnyqpfctg')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idt')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [2]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'udgbfeclrwnhxksvtioqapjmzy')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idu')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [1]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'nrdczqxmowvshaiufblypkjgte')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 10, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idv')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [22], [0]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'hkifjdoacebqtzgulyvmpsxwrn')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iew')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [25]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'yptzuhofqvnmlkgbixwcejsrad')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iex')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [24]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'vkdcwhqfjibzsptngumoraeyxl')
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (3, 11, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iey')
+ self.assertEqual(self.enigma31.peg_positions, ([8], [21], [23]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'wenpbqrouxlkychdfgzvitajms')
+
+ def test_double_advance_with_ring_settings_2(self):
+ self.enigma31.set_wheels('a', 'y', 't')
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayt')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [2]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayu')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [1]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 5, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayv')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [1], [0]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (21, 6, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azw')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [0], [25]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bax')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [24]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bay')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [23]))
+
+ self.enigma31.set_wheels('a', 'z', 't')
+ self.assertEqual(self.enigma31.wheel_positions, (21, 6, 22))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azt')
+ self.assertEqual(self.enigma31.peg_positions, ([16], [0], [2]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 23))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bau')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [1]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 7, 24))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bav')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [25], [0]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 25))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbw')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [25]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 0))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbx')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [24]))
+
+ self.enigma31.advance()
+ self.assertEqual(self.enigma31.wheel_positions, (22, 8, 1))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bby')
+ self.assertEqual(self.enigma31.peg_positions, ([15], [24], [23]))
+
+
+ def test_encipher_with_ring(self):
+
+ self.enigma31.set_wheels('i', 'z', 'd')
+ ct = self.enigma31.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure')
+ self.assertEqual(ct,
+ 'apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki')
+ self.assertEqual(self.enigma31.wheel_positions, (4, 9, 10))
+ self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jch')
+ self.assertEqual(self.enigma31.peg_positions, ([7], [23], [14]))
+ self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase),
+ 'mopnigfuesqwadbcktjrhylzvx')
+
+ self.enigma31.set_wheels('i', 'z', 'd')
+ pt = self.enigma31.decipher('apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki')
+ self.assertEqual(pt,
+ 'verylongtestmessagewithanextrabitofmessageforgoodmeasure')
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file