Enigma emulator

After my recent visit to Bletchley Park I got the urge to write an Enigma emulator.

Background

There are many excellent sources of Enigma information on the net. The wikipedia pages were very useful. Though none of the mentioned emulators were useful to me. Either they only ran on Windows, or didn't fully emulate the machine. Of course I've since found many other sources of Enigma information and at least one quite functional emulator.

Regardless, I was interested in writing this emulator, to confirm my understanding of how the machine worked.

Python

I chose to write in Python because it is highly portable, and emulating a machine screamed for an object oriented approach. The end result is reasonably compact:

$ wc -l enigma/*py
     191 enigma/enigma.py
      63 enigma/plugboard.py
     230 enigma/rotor.py
     484 total
$

Rotor

As can be seen above the rotor is the most complex component, and certainly was the bulk of the effort, though the initial implementation was only 100 lines. It was also the obvious starting point.

My initial design was very simple, each rotor instance, had a transform - essentially just an array of letters of the alphabet in the correct order for each rotor (per the wikipedia rotor page) and one or more turnover positions (when the next rotor is caused to rotate).

Apart from the transform, each rotor had to track its position (what letter is being displayed), and the offset of the transform from the alphabet ring (default being 0). Each rotor also has to know the next and previous rotors, so they can cause the next rotor to rotate when needed, and can invoke its transform.

The reflector is just another rotor instance, that does not rotate and triggers the reverse transform.

Run by itself rotor.py serves as a simple unit-test.

An extract from pydoc:

    class rotor
     |  Methods defined here:
     |
     |  __init__(self, name, conf={}, offset=0, previous=None, next=None, debug=0)
     |      create rotor instance using transform and turnover points from conf
     |
     |  __str__(self)
     |
     |  display(self)
     |      indicate the letter that would be visible for this rotor.
     |      The request is passed on to the next rotor first.
     |
     |  rotate(self)
     |      rotate this rotor one step.
     |      Check the turnover notches (if any) and call next rotors
     |      rotate method if needed.
     |      Only the 3 right most rotors step.
     |      The 2nd rotor can double step.
     |
     |  set_position(self, position)
     |      initialize the position of a rotor
     |      This is how the session key is set.
     |
     |  transform(self, c, backwards=False)
     |      Transform c according to this rotor's wiring.
     |      Pass on to previous or next rotor based on value of backwards.
     |      If we are the reflector we set backwards True.
     |

DATA
    Rotors = {'A': {'transform': 'EJMZALYXVBWFCRQUONTSPIKHGD', 'turnover':...

The Rotors dictionary makes it trivial to lookup a rotor, and pass the dictionary value to the constructor.

Although the existing rotor definitions all match the real Enigma machine, the implementation is not limited and can handle rotors which have more than just upper case letters.

Pluggboard

The plugboard added greatly to the strength of the machine. It is much simpler to implement in software:

class plugboard
 |  Methods defined here:
 |
 |  __init__(self, pairs=[], debug=0)
 |      create a bi-directional mapping for each pair of letters
 |
 |  transform(self, c)
 |      replace c with its pair or leave as is

Enigma

The enigma class itself is quite simple:

DESCRIPTION
    Most of the complexity is in the rotor class.
    The plugboard is a simple bi-directional transformation.

    By default we emulate a standard 3 rotor machine,
    but can also emulate a 4 or more rotor machine.

    By using the 'thin B' reflector and 'Beta' rotor in the 'A' position,
    we can emulate a 4 rotor machine emulating a 3 rotor machine ;-)

CLASSES
    enigma

    class enigma
     |  Methods defined here:
     |
     |  __init__(self, rotors=[], plugs=[], debug=0)
     |      create an Enigma machine using the supplied rotors and plug pairs
     |
     |  cipher(self, str)
     |      process a string of input and output in 4 letter groups
     |
     |  process(self, c)
     |      Each input char is first transformed by the pluggboard,
     |      then the right most rotor (after stepping), which in turn invokes
     |      the other rotors forwards and backwards.
     |      Finally the plugboard has a final chance to transform the result
     |      from the rotors.
     |
     |  set_key(self, key)
     |      Set each rotor to its initial position

Verification

Verifying that we produce correct results is obviously important. Fortunately there are a number of sites which provide useful examples.

Tony Sale's worked example was very useful for verifying basic operation. Unfortunately his simulator for the more complex examples just didn't work with any browser I could find (and the site appears to be unmaintained at this point).

Later, the DIY Enigma Machine was useful for verifying behavior with more interesting initial positions etc.

But my original concept for handling ring offsets (rotate the transform), just didn't work. I tried several variations, but none of them worked correctly.

I knew they didn't work since neither the simple examples on wikipedia nor Tony Sales examples that involved ring offsets produced the expected results.

Finally I came across Mike Koss's pages - refered to from DIY Enigma Machine and found his enigma-sim simulator (in javascript), which accurately emulates a 3 rotor machine.

Ah! rather than represent the transforms as letter substitutions, Mike represented them as letter shifts (eg. rather than A->E, you add 4 to what ever letter you came in with). This is actually a better representation of what the wiring in a rotor does, and not only handled ring offsets correctly, it also simplified the transform process in general. Using that transform my emulator correctly handled all the examples I could find.

Here's a cool example:

echo HELLOXWORLD | ./enigma.py -R I,V,II -O 1,2,3 -P AE,IO,UW -K FOO -
IDJA TJCH ABZ
echo IDJA TJCH ABZ | ./enigma.py -R Beta,I,V,II -O 0,1,2,3 -P AE,IO,UW -K AFOO -
HELL OXWO RLD

That is encrypting a message with a 3 rotor machine, and decrypting it with a 4 rotor machine in the 3 rotor setup (4th rotor in A position). When there are more than 3 rotors it defaults to the thin B reflector which was standard on the 4 rotor machines.

You can get various levels of debug output, compare this to Tony's worked example:

$ ./enigma.py -R I,II,III -K AAZ -d G
Type     | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | Turnover
B        | Y R U H Q S L D P X N G O K M I E B F Z C W V J A T | [] (0)
I        | E K M F L G D Q V Z N T O W Y H X U S P A I B R C J | [] (0)
II       | A J D K S I R U X B L H W T M C Q G Z N P Y F V O E | [4] (0)
III      | B D F H J L C P R T X V Z N Y E I W G A K M U S Q O | [21] (0)
3: position A 0
2: position A 0
1: position Z 25
1: rotate -> 0 [A]
1: G -> C
2: C -> D
3: D -> F
R: position A 0
R: F -> S
3: S -> S
2: S -> E
1: E -> P
AAA
G -> P
P
$

The AAA represents what would be displayed by the rotors. If we bump the debug level a notch we see more info about the transforms:

1: G -> C (i =  6, shift = 22, position =  0, offset =  0)
2: C -> D (i =  2, shift =  1, position =  0, offset =  0)
3: D -> F (i =  3, shift =  2, position =  0, offset =  0)
R: position A 0
R: F -> S (i =  5, shift = 13, position =  0, offset =  0)
3: S -> S (i = 18, shift =  0, position =  0, offset =  0)
2: S -> E (i = 18, shift = 12, position =  0, offset =  0)
1: E -> P (i =  4, shift = 11, position =  0, offset =  0)

where i is the index of the incomming letter, shift is the result of looking up i + position - offset in the transform map.

And to wrap up, here is the 4 rotor (in 3 rotor mode), doing the same thing:

$ ./enigma.py -R Beta,I,II,III -K AAAZ -d G
Type     | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | Turnover
thin B   | E N K Q A U Y W J I C O P B L M D X Z V F T H R G S | [] (0)
Beta     | L E Y J V C N I X W P B Q M D R T A K Z G F U H O S | [] (0)
I        | E K M F L G D Q V Z N T O W Y H X U S P A I B R C J | [] (0)
II       | A J D K S I R U X B L H W T M C Q G Z N P Y F V O E | [4] (0)
III      | B D F H J L C P R T X V Z N Y E I W G A K M U S Q O | [21] (0)
4: position A 0
3: position A 0
2: position A 0
1: position Z 25
1: rotate -> 0 [A]
1: G -> C
2: C -> D
3: D -> F
4: F -> C
R: position A 0
R: C -> K
4: K -> S
3: S -> S
2: S -> E
1: E -> P
AAAA
G -> P
P

Note how with the combination of Beta as 4th rotor and thin B reflector, the trasform for the 4th rotor through the reflector and back out the 4th rotor is equivalent to the normal B reflector (F -> S).

Download

You can download the emulator from http://www.crufty.net/ftp/pub/sjg/enigma-py.zip


Author:sjg@crufty.net /* imagine something very witty here */