Enigma-X is a software application of mine that currently includes an implementation of the Enigma I, and an original variant called Calculus.  Being entirely software based, Calculus is not limited by all the physical constraints that applied to the original physical Enigma.  It’s a “for fun” project I have been working on for a while, and stems primarily from my background as a software developer and interest in history.  It’s also important to note that I am not mathematically inclined, nor am I particularly knowledgeable in cryptography.

1. Logical Design

One way to understand Calculus is to compare it to Enigma I, specifically in terms of the logical design of the rotor components – excluding the Plugboard (Steckerbrett) which Enigma I also used.

Enigma I – Logical Rotor Design

  • Rotor components: stator (input/output), three rotors, reflector.
  • The rotors are arranged into “slots”, numbered from 1 to 3 (left-to-right).
  • Data flow (via the stator) is initially right-to-left (i.e. from slot 3) before passing through the reflector and then back out left-to-right.

Logical Wiring - Enigma I

Calculus – Logical Rotor Design

For direct comparison, the example shown here uses three rotors, although practically you can use any number of rotors that your platform will support.

  • Rotor components: stator (input/output), N-rotors, stator (input/output).
  • The rotors are arranged into “slots”, numbered from 1 to N (left-to-right).
  • Data flow is either:
    • Right-to-left, i.e. (via the right stator) slot N to slot 1, then out through the opposite stator, or
    • Left-to-right, i.e. (via the left stator) slot 1 to slot N, then out through the opposite stator.

Logical Wiring - Calculus

As Calculus is software the physical concepts of left and right don’t strictly apply, however conceptualizing it in this way may make it easier understand.

Calculus (v1) comes with several rotor-sets: 3 x 113 rotor-sets (respectively called Calculus, George and Scherbius), and a collection of 37 x 31 rotor-sets called Cracker.

Comparison of Enigma I to Calculus using the Cracker rotor-set collection:

Enigma I Calculus
Supported Character Set 26 characters: A-Z 94 characters: A-Z a-z 0-9 (space) ! @ # $ % ^ & * (  ) _ – + = { } [ ] | \ ; : ‘ < > , . / ? ` ~
Available Rotors 5 rotors, plus 3 reflectors 1147 (Cracker rotor collection)
Number of Rotor used 3 plus a reflector N (as configured by the operator)
Rotor Stepping Rotors only (not reflector), single direction, regular stepping. Bi-directional, regular stepping.
Plugboard (Steckerbrett) Yes No (but may be added in future versions)

Other differences:

  1. A side effect of the Enigma I’s reflector is that no letter can be encrypted as itself, which weakens cryptographic strength. Calculus does not have this limitation.
  2. Calculus is designed so that data flow through all the rotors, in one direction. The operator can choose which direction to pass the data, either right-to-left or left-to-right.  This means that to successfully decrypt data the operator must the opposite direction to that which was used to encrypt it.
  3. Rotor reuse – there are two ways of looking at this: what is supported by the devices, and what is supported by procedure. Enigma I could reuse the same rotor design (wiring) more than once, but this was not the intended procedure. Calculus can reuse individual rotors as many times as desired as there is no physical limitation.

Key Size

I’m still working this out – here’s a diagram which shows the different variables that influence the key size.

Key to Encipherment 2


2. Operation

Calculus v1 - 001

Operation: Key Setting

First let’s start with some definitions:

  • Algorithm: any cryptographically relevant parts of the system that are built into the device, and which cannot be configured by the operator (e.g. the wiring of the standard rotors).
  • Key: any cryptographically relevant settings of the system which can be configured by the operator (e.g. rotor selection and order).

The freedom provided through the nature of software (versus physical devices) presents some additional key settings that weren’t practically available to operators during world war II:

  1. Selecting the number of rotors.
  2. Specifying rotors – in that the re-use of identically wired rotors is possible. I’m not sure what impact that has on cryptographic strength if operators do this, but it does increase the number of possible permutations.
  3. Rotor step direction – each rotor can step forwards or backwards. Static is also possible but hasn’t been implemented.

Calculus v1 comes with more than one rotor-set, but as these are part of the algorithm their secrecy should not be relied upon (especially for a freely available piece of software).  That said, being software based it’s practically possible for operators to agree on alternative rotor wirings as they see fit, and extension of the software to allow operator defined rotors would not be hard.  The practical difficultly for operators would be to securely share them.

The increased flexibility in key setting results in some practical considerations around how to manage and set keys.   There’s two parts to this:

  1. How keys are stored.
  2. How keys are defined.

Key Storage

As this is a “for fun” project, a design decision was made that key settings can be saved within the application.  Should a third-party gain access to your Calculus enigma they would have access to your keys – the implications are similar to those faced by the Germans in the event of foreign powers capturing a physical enigma and code books containing the key settings.

An advantage of saving keys, pre-defined by the operator, is that they can be recalled by a (for example) a PIN number without having to be exposed.  There’s more detail to this area in general, but it’s not so relevant to this introductory essay.

Key Definition

Being able to set 100+ rotors presents practical challenges. For a start, it’s a lot to manage – being able to memorize something like that is certainly not something I can do, plus it’s a lot of work to manually (and correctly) set it up each time.

Calculus gets around this by offering a couple of key-setting methods:

  • Manually setting individual rotor settings, and then saving them for easy and consistent reuse.
  • Algorithms, which given a short and simple syntax allow you to easily set lengthy keys – of course that comes with its own set of problems.

In simple terms, key setting in Calculus is done like this:  Start by creating a new key setting – referred to in Calculus as a “Rotor Config”.  The rotor config includes: a name, a PIN number (for easy and “secure” recall), a rotor selection algorithm, and an algorithm value.

Calculus v1 - 002

The rotor-set to be used is not specified as part of the key (and therefore is not saved), nor is the encryption direction (left-to-right or right-to-left).

The critical parts of the key are the rotor selection algorithm and algorithm value; each algorithm expects a specific syntax, which is discernible if you know the algorithm value.  The best way to explain is by example.

“Selektor” is the provider to use if you want to individually specify each rotor.  The syntax is a.b.c[/a.b.c] where a, b and c are integers; a is the index of the rotor, b is the starting position of the rotor, and c is the step direction.  These values are specified in order, separated by full stops.  The key can contain as many of these triplets as you like, separated by forward slashes “/”.  For example, 0.0.1/5.0.1/100.33.1.

In a software programming context, the rotors and character-positions are zero-based arrays; the first item is always at an index position of 0, so in an array that contained 10 items, the last item would have an index position of 9.  The values a and b refer to the zero-based index positions of the rotor (a) and the rotors starting position (b).  Taking the example above, the first triplet “0.0.1” would select the first rotor from whatever rotor-set you had selected at runtime, and set it’s starting position to 0 (the visible rotor letter “A”); the third triplet would select the 101st rotor and set it to a starting position 33 (the visible rotor letter “h”).

In contrast, the Cracker algorithm takes a specific value of 6 integers, separated by forward slashes: a/b/c/d/e/f – for example: 100/0/1/0/1/1 or another example: 100/50/-3/33/-5/1.

The syntax is thus:

  1. a is the number of rotors to set.
  2. b is the index of the first rotor from the target rotor-set (just like the ‘a’ variable in Selektor).
  3. c is the increment to select subsequent rotors, this number can be any positive or negative integer except for 0. 1 would select the next rotor from the rotor-set (e.g. 0, 1, 2, 3), -1 would select the previous rotor (e.g. 60, 59, 58, 57). Using larger numbers allows you to specify more broadly (e.g. 0, 5, 10, 15; or 60, 55, 50, 45, 40).
  4. d is the index of the starting position of the first rotor.
  5. e is the increment by which each subsequent rotor is set, this number can be any positive or negative integer.
  6. f is the rotor stepping direction (all rotors step in the same direction); 0<= for reverse, >0 for forwards.

The algorithm value is deliberately not tied to a specific rotor-set.  As rotor-sets will have different numbers of rotors, and potentially support different character-sets of different lengths, the algorithm need to consistently handle inputs that fall outside the range of the arrays – such as when wanting to select 100 consecutive rotors, from a 113-rotor rotor-set, starting at index 100.

Calculus gets around this by conceptualizing the array as circular – rather than as a line with two end points.  For example, assuming an array of 10 (and remembering that the valid indexes are therefore 0-9), a value of 10 would be index 0; a value of 33 would be index 4; and index of -3 would be index 7.  It can also safely handle variables bigger than the size of the array – e.g. a rotor selection increment of 197 against a rotor-set of 113 (giving us rotors 1, 85, 56, 27, 111, 82 and so on).  This means that Calculus can consistently handle configuration values against any conceivable rotor and rotor-set.

The Cracker algorithm is of course relatively simplistic and its predictability through regularity is no doubt a cryptographic weakness, but it’s an early example of the types of key generation approaches that Calculus could support.  Its simplicity is possibly also a strength in that a short 6-value key is comparatively easy to memorize, and can represent actual rotor settings that are much larger than itself (i.e. many rotors), and the lack of hard limits, e.g. in terms of the rotors used (number of, and potential reuse of duplicate rotors), leads to a large number of possible permutations.

Rotor-Set Selection

At runtime, rotors are pulled from whatever rotor collection the operator has chosen – which currently would be one of the three 113-rotor rotor-sets, or some combination of the the 37 31-rotor rotor-sets in Cracker.

When using the Cracker rotor collection, the operator can use all 37 rotor-sets (in their default order), or, select any number of rotor-sets in any order by specifying their zero-based indexes, separated by spaces, e.g. 0, 30, 5, 20, 10, or  17, 10, 17, 5, 30, 14, 27.  this means that the same algorithm value can select different rotors, and the rotor-set selection becomes part of the key.

Other Extensions

Because Calculus is software based it’s also possible to implement controls that help mitigate some of the operator errors that led to Enigma being broken:

  • Automatically adding padding (random characters to the plain-text before encryption), and optionally the automatically removing such padding.
  • Denying the re-use of certain key settings.
  • Denying the re-encryption of the same / similar message.

And for fun: taking every n-Letter (i.e. every second letter) so that you had two streams of text, reversing one, then recombining before encryption through the rotors – such a process would help hide cribs.