Julius Caesar was worried. He needed to get a letter back to Cicero, the consul of Rome, but it had to travel through enemy territory. His solution? Shift every letter to the third letter after it, wrapping around so that A became D and Y became B. Here we’ll implement his idea in a computer program.
To have fun with the traditional Caesar Cipher, we need to be able to read in and print out files. We’ll do this using a Scanner and PrintWriter for standard IO, with the methods readFile() and printFile(). To learn more about file I/O, click here.
Shift Cipher – Encode or Decode
The shift cipher is the real workhorse of the Caesar Cipher. It takes a string, converts it to a character array, and does the encryption.
public String shiftCipher(String input, int shift) { String coded = ""; char [] message = input.toCharArray(); for (int i = 0; i < message.length; i++) { char letter = message[i]; letter = (char) cipherUppercase(letter, shift); letter = (char) cipherLowercase(letter, shift); message[i] = letter; } for (int i = 0; i < message.length; i++) { coded += message[i]; } return coded; }
We make an empty string to hold the return value of the encrypted/decrypted message. Then we convert the input to a character array. In the loop, we visit each element of the array and store it as an int – this is allowed for any ASCII character.
Dive deep: Learn more about ASCII characters here!
Then we call helper methods to perform the shift. Calling both cipherUppercase() and cipherLowercase() is fine here because at most one of them will actually modify the value of letter. We convert the integer value returned from these helper methods back into a character by casting. After the letter is modified (if needed), it is stored back in the array. Then we loop through the array again, adding its values to the string coded which we then return.
Cipher Uppercase
This helper method checks if the character is uppercase, performs a cipher if it is, and just returns the value unchanged if it isn’t.
private int cipherUppercase(char letter, int shift) { final int a = 65; // ASCII value for 'A' final int z = 90; // ASCII value for 'Z' int coded = letter; if ((a <= letter) && (letter <= z)) { // Get the value of the letter on a scale of 0 to 25 int azLetter = letter - a; int newLetter = azLetter + shift; // Add the shift int remainder = newLetter % 26; // Get the remainder coded = a + remainder; // Return to ASCII scale } return coded; }
The first thing we notice in this method is the “final” before the first two ints. This “final” means we cannot modify these variables by giving them another value, so the value given when they are declared is their final value. Both final ints are storing ASCII values, so we don’t want to modify them. Usually, we do want our variables to be modifiable, so we rarely use final.
We assign letter to another variable before entering the if-statement. This lets us modify the value comfortably and avoids changing a parameter variable. Then we subtract a from the letter and add the shift. We get the remainder by using the modulus operator which we represent with the percent sign. Then we add the remainder to a, and store this in the coded variable. These steps work whether the sum (letter + shift) is a letter or a non-letter because the remainder for a letter is the same as the remainder for that value plus 26. Finally we return the coded value of the letter.
Cipher Lowercase
It’s pretty much the same as CipherUppercase(), except the values for a and z are changed to match the lowercase ASCII characters:
private int cipherLowercase(char letter, int shift) { final int a = 97; // ASCII value for 'a' final int z = 122; // ASCII value for 'z' int coded = letter; if ((a <= letter) && (letter <= z)) { // Get the value of the letter on a scale of 0 to 25 int azLetter = letter - a; int newLetter = azLetter + shift; // Add the shift int remainder = newLetter % 26; // Get the remainder coded = a + remainder; // Return to ASCII scale } return coded; }
Main – Let’s watch it run
This is a pretty standard main method.
public static void main(String[] args) { TraditionalCaesarCipher self = new TraditionalCaesarCipher(); String original = self.readFile("TradCaesarCipherABC1Orig.txt"); String encrypted = self.shiftCipher(original, 3); self.printFile(encrypted, "TradCaesarCipherABC1Coded.txt"); }
We create an instance of our current class and call it self. Then we read in the original file, perform the cipher, and print out the results to the console and the new file.
One sample run is shown below:
You can try making your own files, as well as downloading the files below to run with it: