Lab #4: Enigma

The purpose of this lab is to practice good OOP practices. You will write a program that encrypts and decrypts messages simulating a simplified version of the Enigma machine used by the Germans in WWII. The machine will be described in detail later, but here are the two key points:

  1. The alphabet for messages is all capital letters, plus # for spaces.
  2. In order to encrypt/decrypt properly, sender and receiver have to agree on the three rotors that will define the enigma setup. We indicate which 3 rotors are to be used with an ordered list of three numbers taken from [1-5], no duplicates allowed. In other words, there are 5 possible rotors, and we indicate which 3 to use for each run of the program.
  3. Each rotor starts on a specific character, so we also input the starting character for each of the 3 rotors.
Here are several sample runs of the program, using just the first 3 rotors (1, 2, 3) in order:

~/$ java Comms 1 2 3 "###" encrypt
BEAT#ARMY
AFUGNRCD#
~/$ java Comms 1 2 3 "USN" encrypt
BEAT#ARMY
PUIVBFRSO
~/$ java Comms 1 2 3 "USN" decrypt
PUIVBFRSO
BEAT#ARMY

When finished, your program will decrypt the following message using the settings 1 2 3 "###":

XXMMJ#UBHRWSHYSSTGWIGMMMAKTFSWZD#PU#CZIQADCDQY#NHN#SJVJTKZVVHOZBABLYMWBWWLNGAWWXEBWNXQQBQQRNMJGYXRYBKISBBFHGOO

Enigma

Our Simplified Model of the Enigma

For the full description of the real enigma machine, read Prof Taylor's lovely writeup.

What you need to know for this lab: Enigma machines used interchangeable rotors that could be placed in different orientations to obtain different substitution patterns. More significantly, the rotors rotated after each character was encoded, changing the substitution pattern and making the code very difficult to break. The behavior of the rotating rotors can be modeled, in a simplified form, by a device consisting of labeled, concentric rings. For example, the picture here has three rings labeled with the letters of the alphabet and '#' (representing a space).

Encryption

To encrypt a character using this model, find the character on the inner rotor (i.e., the inside ring) and note the character aligned with it on the outer rotor (i.e., the outside ring), then find that character on the middle rotor (i.e., the middle ring) and output the one aligned with it on the outer rotor. After a character is encrypted, turn the inner rotor clockwise one step. Whenever the inner rotor makes a full revolution and returns to its original orientation, the middle rotor turns once in lock-step, and when the middle rotor makes a full revolution, the outer rotor turns once in lock-step, just like the odometer in a car.

For example, in this configuration the character 'A' would be encrypted as 'N', since 'A' on the inner rotor is aligned with 'H' on the outer rotor, and 'H' on the middle rotor is aligned with 'N' on the outer rotor. After performing this encryption, the inner rotor is rotated clockwise, so the letter 'A' would next be encrypted as 'D'.

Decryption

Decrypting a message requires following the same steps, only in reverse: Find the character on the outer rotor, note the character aligned with it on the middle rotor, find that character on the outer rotor, then output the character aligned with it on the inner rotor. Don't forget to rotate the rotors after each letter is decrypted.

Cipher Background

Substitution ciphers that encode a message by substituting one character for another go back at least as far as Julius Caesar, who used a rotating character scheme to encode military orders. This simple type of encryption is extremely vulnerable to statistical attacks, however. In World War II, the Nazi military employed an encryption scheme that addressed this weakness of simple substitution ciphers. This scheme, implemented by typewriter-sized devices known as Enigma machines, was believed by the Nazis to be unbreakable. This belief was grounded in the fact that by the time the huge amount of computational work necessary to break the code was completed, the message itself would be irrelevant.

Polish mathematicians, followed by researchers at Bletchley Park, England (led by Alan Turing), built machines known as bombe (from the Polish "bomba kryptologiczna," or "cryptologic bomb") to run through the computation and allow for timely decryption of Nazi messages. This is hailed as one of the turning points of the war, and the first great success of computer science.

Real Enigma Machine

A standard enigma machines used three rotors. Special units had extra for added complexity. You can see the rotors in the picture on the right. A special codebook told the operators which rotors to use and how to orient them to begin each message. The code changed at the same time every night. The job of Bletchley Park was largely to figure out which three rotors were in use that day. Once they did that, they could decode all German military traffic for the day. The channel would 'go dark' again at midnight when the codes changed again.

Prior to encoding or decoding a message, the operator would put the three rotors in and set them to the problem starting position. To encode, they would type the plaintext message on the keyboard and read the output from the 'lampboard'. The lampboard is a set of letters in qwerty layout that light up. So pressing the 'A' in the example above would cause the letter 'N' to light up on the lampboard. Decoding was done in a similar manner.

The plugboard was an additional feature that added complexity to the encoding algorithm. It allowed the machine to swap two letters before encoding. This made decrypting an Enigma transmission by hand much more difficult, and required the use of machines to encode or decode.

Task Requirements

The Task

You will define a class Rotor to simulate the workings of a single rotor, and the class Enigma to simulate the workings of an Enigma machine using Rotor instances. We provide you the Comms class that manages the interface with the user (Comms.java) and contains the main() method. You may not alter Comms.java in any way. Your task is to write both Enigma and Rotor using proper OOP design with class constructors, information hiding, and encapsulation.

The Rotor class

I strongly recommend that you represent the rotor as a 27 character long String — where the element at index 0 is the topmost element, and moving to the right in the String represents moving clockwise around the rotor — and a possibly a single character, which stores the symbol that was initially topmost. Your Rotor should be able to do the following things:

  1. Be constructed, requiring a String that defines the Rotor and a single character defining the symbol that should be initially at the "top" of the Rotor.
    Note: in the constructor, you can call other methods, like the method to rotate (described in the bullet below)!
    When the contructor is finished, the Rotor must be rotated so that character provided is at the "top" of the Rotor.
  2. Rotate one click clockwise. This should involve changing the String. An example is provided below.
  3. Return the index in the String at which a given character appears.
  4. Return the character at a given index.

An example of a rotor String is "#GNUAHOVBIPWCJQXDKRYELSZFMT" ... which you are to interpret circularly, so that the last character loops around to the first. If you imagine that the first positition indicates the top spot on the rotor, then:

#GNUAHOVBIPWCJQXDKRYELSZFMT rotated one click clockwise is T#GNUAHOVBIPWCJQXDKRYELSZFM

The Enigma class

This we leave partly up to you. We expect your Engima to have 5 possible rotors, and when your Enigma class is created, it chooses which 3 to use along with their rotor starting symbols. You must hardcode the 5 possible rotors in your class as the following Strings:

1. #GNUAHOVBIPWCJQXDKRYELSZFMT
2. #EJOTYCHMRWAFKPUZDINSXBGLQV
3. #BDFHJLNPRTVXZACEGIKMOQSUWY
4. #NWDKHGXZVRIFJBLMAOPSCYUTQE
5. #TGOWHLIFMCSZYRVXQABUPEJKND

You must also have encrypt and decrypt methods for encrypting and decrypting strings. These must be compatible with the Comms.java file that we give you. The behavior in these methods must follow the enigma procedure described above in "Our Simple Model of the Enigma".

The Comms class

This is the program's main class. We provide this to you (Comms.java) and you may not change it in any way. The program takes as input (from the command line) the three rotors and their starting characters. A correct call to the program Comms will provide all the information needed to setup enigma for that encryption/decryption session on the command-line, and the actual string to encrypt/decrypt should be input from standard in.

                  ,-- inner rotor initially positioned so X is on top
                  |,-- middle rotor initially positioned so # is on top
                  ||  ,-- outer rotor initially positioned so Y is on top
                  || /
java Comms 4 2 3 "X#Y" encrypt
           | | |
           | | `-- outer rotor is rotor 3
           | `-- middle rotor is rotor 2
           `-- inner rotor is rotor 4

A couple example runs are here. You must also make your own tests and fully test your code:

~/$ java Comms 1 2 3 "###" encrypt
AAA
NDU
~/$ java Comms 3 1 2 "SAT" encrypt
DO#YOUR#BEST#AND#KEEP#ON#KEEPIN#ON
ACAAFAEOZFWKBQKPXZOGIKXTNPEBDXWQCZ
~/$ java Comms 5 2 4 "EST" decrypt
CSHIAWDFGDCOE#EZKJHRWAZDDCBCILON#PKUJEXEXSHINZ
THE#NATIONAL#ANIMAL#OF#SCOTLAND#IS#THE#UNICORN

Submission

Do not submit Comms.java. We will test with our version. You didn't change Comms, right? Right??

~/bin/submit -c=IC211 -p=Lab04 Enigma.java Rotor.java



Acknowledgments

The original version of this lab by Prof. David Reed, Creighton University.