For the second project you will practice coding with loops by implementing several ciphers. For full credit you will have to implement Cesar's and Vigenère's ciphers - ciphers that change the letters in a text to a different set of letters so that the meaning is hidden from anyone who doesn't have the decryption key. For students looking for an extra challenge I have also created a template for a transposition cipher - this one simply shuffles the text in a predictable way.
The starter code you get includes a separate .java file for each of the ciphers, and within it I have created stubs for an 'encrypt' and a 'decrypt' method and that's where all your code will need to go. Three variables have already been created for you, corresponding to the text to be encrypted or decrypted (text), the key (key), and the output string (output). The text and output are of String type, and the key is an integer for Cesar's and the block ciphers, and a String for Vigenère's cipher.
The starter code also provides the following interface:
- You are prompted to enter a text and a key on separate lines
- You are then prompted to decide whether you want to 'encode' or 'decode' the corresponding text
- The program then runs the appropriate method (encrypt or decrypt) for you and outputs the results
There are several assumptions made by this code and the testing code:
- The text being encrypted contains only alphabet letters (A-Z) without spaces or punctuation marks
- The text is exactly one line
- The integer key is between 0 and 25 for Cesar's cipher
IMPORTANT: You do not have to check that these conditions hold, and the testing code will make sure to only give you inputs that satisfy these conditions. However, note that if you enter incorrect input when interacting with the code you may get errors (my stub code does not prevent you from accidentally crashing your code).
IMPORTANT: For a variety of reasons it makes sense to encrypt text that is all uppercase. You must make sure to convert the input text to uppercase before performing any operations on it.
Please carefully read the description of the ciphers below as well as the HINTS section.
The Caesar cipher encrypts a message by shifting each letter a certain number of characters. For example, if the shift is 3, then “A” would become “D”, “B” would become “E” and so on. The Caesar cipher “wraps around”, “Y” with a shift of 3 would become “B”, “Z” with a shift a 3 would become “C”. The message “ATTACKATDAWN”, with a shift a 5 is encrypted as “FYYFHPFYIFBS”.
See more details here: https://en.wikipedia.org/wiki/Caesar_cipher
The Vigenère cipher encrypts based on a keyword; to encrypt each letter of the message is shifted, as in the Caesar cipher, but by a different amount, depending on the current letter of the key. In the keyword, a letter “A” represents no shift at all, “B” a shift of one, and so on. Since the keyword is very likely shorter than the length of the entire message, the keyword is repeated as many times as necessary to encrypt the entire message. For example:
Repeated key: LEMONLEMONLE
For more details see: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
Transposition cipher (ungraded challenge problem)
The transposition cipher simply shuffles the text in a predictable way. The algorithm I am asking you to implement takes a string and an integer key. Then it performs the following steps:
- The text is padded with the dummy character 'X' so that its length is a multiple of the key
- The text is organized in row-first order in a table where each row is the length of the key
- The encrypted text is reported by outputting the table in column-first order
The decryption reverses this process by simply running the encryption procedure with a key equal to the integer ratio between the length of the text and the length of the key.
An example may help make this explanation more clear:
encrypted text: AKWTANTTXADXCAX
updated key = 15 / 5 = 3
decrypted text: ATTACKATDAWNXXX
Note that you do not have to actually create the table, rather you can simply 'simulate' it by skipping over 'key' characters as you visit the string.
- The .charAt() method allows you to access a specific character within a string.
- In Java, you can cast a char to int, and vice-versa. Casting a character to an int will give its ASCII value. “A” in ASCII is the number 65.
- In Java you can perform arithmetic operations on characters. For example:
int x = (int) ('C' - 'A'); // x = 2
You can use this to 'shift' characters in the alphabet, or to determine the index of a letter in the alphabet ('A' is the zeroeth letter, B is at index 1, C at index 2, etc.)
- You must be careful to 'fold over' when going past 'Z' when encrypting or past 'A' when decrypting, otherwise the string you return will be nonsensical. For example, 'Z' + 1 should return 'A' instead of '[', and 'A' - 1 should return 'Z' rather than '@'.
- The modulo operator '%' can help you loop around a string or the alphabet. For example, if the index of a letter is 'idx' and the key is 'key', the value '(idx + key) % 26' will automatically loop to the beginning of the alphabet if the resulting value goes past 'Z'. The actual character can be obtained as the expression ' (char) (idx + 'A')'
- You can append characters to the end of a string using the '+' operator as we have done when using println. Note that this approach is very inefficient, but this won't be an issue for this project. We will learn better approaches later in the class.