CS35 Lab 2: The Enigma Machine

Due 11:59pm Tuesday, February 4, 2014

The goal of this lab is to introduce you to basic concepts in the C++ program language. Concepts you will be familiar with after this lab include:

A skeleton version the program will appear in your cs35/labs/02 directory when you run update35. The program handin35 will only submit files in this directory. In this and most future labs, you'll work with one partner (there is one group of three). I am assigning partners for this lab; find your partner in this file. Useful links: In the extras directory of this lab, there are a couple of text files, along with encryptions of each file using each encryption scheme you'll have to implement for this lab. Use these to compare against your encrypt implementations, and compare your decrypted files with the original text file to make sure you're encrypting and decrypting correctly.

Introduction

Encryption is the process of encoding messages in such a way that only authorized parties can read the message. The idea of encrypting messages is thousands of years old and has been particularly useful in the military, where it is important to exchange messages (e.g. "Attack at dawn!" vs "Hold your ground") without enemies being able to understand them in the event a message is intercepted. A cipher is a kind of encryption scheme where each letter is replaced by another. Ciphers have been used since at least Roman times. Julius Caesar used an cipher where each letter of the message was replaced with one three positions earlier in the alphabet. So, for instance, 'A' is encrypted as 'X', 'B' becomes 'Y', 'C' is encrypted as 'Z', 'D' is encrypted as 'A', and so on. An encrypted message is called the ciphertext, and if an enemy intercepted a message, it would just look like a jumble of letters. On the other hand, Caesar's subordinates, knowing the encryption scheme, could decrypt the message by employing doing the opposite of the encryption scheme: 'A' is decrypted as 'D', 'B' is decrypted as 'E', etc. This cipher was used so effectively that it became known as the Caesar cipher. In this lab, you will implement the following ciphers:

The Allies made a huge effort to break the Engima code during World War II. This task was led in part by Alan Turing, and it was said that breaking the enigma machine shortened the war in Europe by two years. The effort to break German ciphers also resulted in the first electrical digital computers.

The essential flow of your program will be as follows: The user specifies whether they want to encrypt or decrypt. Then they must specifiy input and output files and the cipher they wish to use. Finally, your program must use the requested cipher to encrypt or decrypt the input file, writing it to the output file.

Program Requirements

I recommend implementing your lab assignment in 4 phases:

  1. File Input and Output - be able to read in a text file and output it without loss of information.
  2. ROT13, Substitution ciphers - implement all the ROT13 and Substitution ciphers and verify that they correctly encrypt and decrypt text.
  3. Implement a menu-based interface - fill in your program by adding user interaction to choose (i) whether to encrypt or decrypt and (ii) which cipher to use.
  4. Enigma Cipher - complete the lab by implementing the Engima cipher.
Your program should use proper design. That is, your program will be tested on your use of modular functions and understanding of how to call, define, and declare functions in C++.

Deliverables

You should complete the following items:

  1. enigma.cpp This file will contain your entire completed assignment
  2. any encrypted files or decrypted files you feel will show the graders that your ciphers work as advertised.
  3. README Answer a few short questions in this file

I. File Input and Output

Your program will need to handle opening, reading, closing, and writing to file.

Example text files are available in the input folder in your labs directory for this week.

Review of requirements before moving forward:

II. Encryption and Decryption Functions

Once you are able to replicate a text file, you can begin writing your encryption and decryption functions. At this stage, you should implement encryption and decryption functions for the Caesar, ROT13, and substitution ciphers. Hold off on implementing the Enigma cipher until the last stage. Let's begin with the encryption function for the Caesar cipher.

In all cases, do not just test using input/sample.txt. Also encrypt and decrypt several larger text files, with more varied text, to ensure you handle encryption and decryption in all cases.

Managing the encryption and decryption. So you read in a letter 'K' and are encrypting using the Caesar cipher. How does your lab figure out that 'H' is the encrypted character? More generally, with an arbitrary cipher, how should the data be structured to manage the encryption? There are several different possibilities, but the most straightforward is to use arrays. In the case of the Caesar cipher, the most straightforward solution is to use a character array:

    char alphabet[] = {'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'};
  
When encrypting a character, search through this array (using a for loop) until you find the index of the character to encrypt. Then subtract 3 from the index and output that character. Warning: you will need to handle the case where the cipher "wraps around" e.g. when you want to encrypt 'B' as 'Y'.

Managing arbitrary substitutions in the substitution cipher. The Substitution cipher allows arbitrary substitutions. You should enable the user to pick any permutations she likes. To enable arbitrary permutations here, load a substitution alphabet from a file and store it in a second character array. The format of your file should be just a permutation of characters, such as the example in input/subalpha:

    KJRTPEQFBHYLZDOCMASWUVNXIG
  
Your substitution cipher should take this setting and use it to encrypt 'A' as 'K', 'B' as 'J', 'C' as 'R', and so on.

Handling nonalphabetic characters. In this lab you can assume that the text consists of all capital letters, along with possibly some whitespace, which you can ignore. What happens if the text contains characters which are not capital letters, such as lower case letters, numbers, or punctuation? For this lab, feel free to ignore these characters -- if one appears, just leave it out of the encryption and read in the next character. In the real world, these characters might be (i) ignored, (ii) written to the output file without encrypting them, or (iii) encrypting them using some other means. Again, for this lab, you should ignore these characters.


III. Implementing the User Interface

The overall design of your program should be as follows:
Greet user.
Ask user if they want to encrypt, decrypt, or exit.
Repeat the following until the user chooses to exit.
  Ask user for input file (check if valid)
  Ask user for output file
  Ask user which encryption/decryption scheme he/she wants to use.
  If necessary, load settings for the chosen encrypyion/decryption scheme.
  For each character in the text:
    read in the character
    encrypt or decrypt the character using the cipher chosen by the user
    write character to output file.
  Close input and output files.
There are multiple ways to implement this user interface. One possible solution is to implement three menus:

Your program should either encrypt or decrypt the chosen input file as demanded by the user. At all times, you should practice defensive programming.


IV. Implementing the Enigma Cipher

For the final part of your lab, you'll implement a simplified version of the Enigma Machine cipher. Warning: this is more complicated than previous ciphers, and I strongly recommend you get the rest of your lab working first. An Enigma machine uses three rotors. Each rotor (call them the inner, middle, and outer rotors) contains some fixed permutation of the letters. To encrypt a character c, perform the following:
  1. Locate c on the inner rotor.
  2. Find the character on the outer rotor aligned with c. Call this character c'.
  3. Locate c' on the middle rotor.
  4. Find the character on the outer rotor aligned with c'. Output this character.
After encrypting a letter but before encrypting the next letter, you must move the rotors in the following way:
  1. Move the inner rotor clockwise one position.
  2. If the inner rotor is now back in the start position, also move the middle rotor.

Initial Enigma Settings. Like the substitution cipher, you should read in from a file both (i) the initial offset for the inner and middle rotors and (ii) the fixed permutation for each rotor. The format for this file should be as follows. The first line contains integers denoting the inner rotor offset and middle rotor offset respectively. The second, third, and fourth lines contain the information for the inner, middle, and outer rotors respectively. There is an example enigma settings file in input/enigmasettings.

Hint: to implement the enigma cipher, I recommend using character arrays for each rotor. Use integer variables (say inner_offset and middle_offset) to maintain the offsets. In this way, the state of the inner rotor would be implemented with (i) an array of chars and (ii) an offset. If 'D' is the first element of the array and the offset=3, then this character would align with the fourth character in the outer array.

Hint 2: decrypting the enigma cipher can seem complicated, but you still want to do essentially the opposite of the encryption. Specifically, perform the following:


Review of Requirements and Sample Results

Submit

Once you are satisfied with your code, hand it in by typing handin35. This will copy the code from your cs35/labs/02 to my grading directory. You may run handin35 as many times as you like, and only the most recent submission will be recorded.


Acknowledgments

The Enigma Machine cipher part of the lab is based on David Reed's NIFTY 2009 submission entitled "Enigma Encryption".