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:
~/$ 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
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).
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'.
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.
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.
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.
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.
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:
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
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".
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
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
The original version of this lab by Prof. David Reed, Creighton University.