Why I tried making this.
I was listening to a podcast about forensic linguistics and cryptography recently (Dr Claire Hardaker's En Clair podcast. (My thanks to A.P. for recommending it to me.) There was a series of episodes discussing the history of the Enigma Machine. Hardaker's explanation of the algorithm the Enigma Machine used seemed fairly straightforward, so I wanted to test my understanding of it by trying to replicate something that used the same principles.
It was also a fun opportunity to test my knowledge of coding. It has been a while since my last project, and this one was much simpler and more straightforward than the personality quiz I made. It's all a bit of fun at the end of the day.
Please enter the settings for the cypher, and then the plaintext or cyphertext in the field below. The cypher is reciprocal, so it will encrypt and decrypt inputs using the same key and input.
How I went about making this.
This project took me the greater part of a day, from start to finish.
I really don't like writing .html. I saved a lot of time by copying and pasting my old bits of code. I straight up cheesed it by copying the layout from the Personality Quiz wholesale. There were several things I didn't quire remember off the top of my head to code, and I did not remember which references I consulted to find the syntax, so I just lifted tracts of code from my previous projects. This was mostly for the .html web site and the CSS code for the interface. The actual algorithms of the cypher had very little in common with the personality quiz.
As for the cypher itself, I used the general principles of the Enigma machine: there are a series of 'rotors' that encypher a character input to a different output. Each rotor has a unique, randomised scrambling of inputs to outputs. The plaintext goes through three layers of rotors. Each character advances the first rotor by one increment, thereby changing the cypher for the next character. Once the first rotor completes a full cirlce, it increments the second rotor; and likewise the second increments the third on a full rotation. This method of incrementing rotors creates a polyalphabetic cypher where the substitutions are randomised and changing for every successive character.
Once the input has gone through all three rotors, it is processed by a 'reflector' that reverses the input through a different route. There are three patterns that the reflector uses, a symmetrical one (where the top character is mapped to the bottom, the second from the top to the second from the bottom, etc), one where the first character is dropped and successive pairs of characters are mapped to each other, and one where the last character is dropped and successive pairs are mapped to each other.
Once the altered input is reversed, the algorithm traces the newly-mapped output backwards through the three rotors. Once the output passes back through all three rotors, the rotors are advanced and the next character is processed. The process is iterated for each character in the input text.
Unlike the Enigma rotors, which had 26 characters, I made this programme to work with all 95 basic Latin Unicode characters. This obviously meant that the number of possible combinations of for rotors is significantly increased compared to the original Enigma machine by nearly 50 times. This also means it can encode upper and lower case letters separately, as well as numbers, and most basic punctuation marks.
I was tempted to use a more expanded Unicode character set and include diacritics and emojis. This would have not only made the cypher work for more characters, but also dramatically increase the possible combinations of rotor alignments. However, the admissible series of Unicode characters (in particular when trying to avoid control characters) is discontinuous, making the management of iterated loops more fiddly. So I decided to keep it simple.
There were a number of peculiar quirks that resulted from this set-up. The first is that there are an odd number of characters for me to work with. This meant that one character would always end up mapping back to itself (47th character in the first reflector, the first and the last in the remaining two). This is a relatively small downside. I was considering shifting the characters to map on to a different letter before reversing the input, but I decided to keep the mirroring and allow one character to map onto itself so that I could make the system reciprocal. That way, the same key can be used to encypher the plaintext and decypher the cyphertext. Again, this was true to the Enigma's original design. It's just that it worked with an even number of characters instead.
Another quirk was that I needed to control for line breaks. I had to make sure line break characters were not encyphered because their characters are very far away from the rest of the Unicode characters I was using. I had to set up an input validation algorithm which checked the input for invalid characters and also allowed line breaks to pass through unencrypted.
Once I got the basic algorithm working, I generated some randomised cypher arrays for the rotors and made six different arrays which can be configured in any permutation, the same with chosing a different kind of reflector in the settings. I also set up a system for offsetting their alignment at the start of the message, allowing for the use of a randomised cypher key to add a further layer of security.
This is where I encountered my first limitation of not knowing how exactly the Enigma Machine worked. I wasn't sure if the change in alignment of a rotor meant the advancing of the rotor to the stated increment, or the re-alignment of the cypher relative to the rotor itself while the rotor was still at an increment of 0. Basically, it's the difference between skipping the rotors ahead by x number of characters (thus you are x characters closer to the next rotors incrementing) or moving all characters along x places while the rotor was still at zero. I felt like the latter was the case, and indeed the latter was more effective at preventing replicating patterns, so I went with that instead.
On the whole, the cypher seems to be working okay. The algorithms and the mappings of rotors are somewhat transparent as the code is easy to see, meaning the strength of this system ultimately rests on how secure the keys are (even though they are hard to guess).
When I was thinking through the Enigma machine, I was thinking of how the signals were transmitted in semantic terms: how each successive rotor substituted the inputted letter into a different letter. This was how Hardaker explained it on her podcast. I realised very early on that semantic operations, where I convert a letter into another letter, and then into another letter at the next rotor, would add too many redundant steps to the algorithm.
This is because, in the same way the Enigma machine processed inputs by converting them to electrical signals, the code for this cypher converts inputted characters into a Unicode value for the character. While the Enigma rotors physically wire signals from one letter to another, this cypher does mathematical operations on the Unicode values to change the charcter. Converting the Unicode value back into a character and then again into a Unicode value would have been redundant. So rather than assign any of these rotors any semantics by which elements would correspond to a letter, I just left them as purely symbolic substitutions of different Unicode numbers, which would only be encoded and decoded at the last step of the algorithm. This way, the individual rotors themselves are a little more difficult to read even if someone were to access the code.
This meant a lot of fiddly arithmetic to ensure that the values wrapped around the upper and lower bounds of the list of characters correctly, and I am still not entirely sure I understand modulus operations to do this.
I might come back to this project again to tidy it up and to streamline some of the code. Unlike the personality quiz, which took a long time to make because of having to write the questions, this is fairly straightforward as it only uses mathematical calculations. It was certainly a lot less of a 'creative' endeavour compared to the personality quiz, since this doesn't really tell a story but merely does calculations.
A summary of this cypher's development.
27 June 2020
I would really much rather you used Chrome.
If you notice any incompatibilities or strange browser behaviour, please let me know and I'll try and see how I can fix it.
Apparently, some ad blockers interfere with the CSS code. So they have somehow messed with links on the page.