ulrail.gif

HW 6: Methods

  ur-2c.gif urrail.gif
blrail-nonavbar.gif

Home | Resources | Homeworks | Exams
Lectures | Labs | Contacts | Submit | TAs

br-2a.gif   br-2c.gif brrail.gif
spacer.gif spacer.gif

Purpose

This homework has several purposes.
  • To help you understand programming using methods
  • To show you how to build upon smaller methods to achieve larger methods.

  • To introduce you to an interesting problem area, namely cryptographic algorithms.  We introduce the Caesar Cipher here.  Although one of the most basic encryption algorithms; it was used (very successfully) by Julius Caesar to communicate with his generals.

All of your code should be in a public class CaesarCipher, and in a CaesarCipher.java file.  We are not providing any skeleton code.  There are a five methods in this homework, all of which are described below.

Background

In cryptography, plaintext is information used as input to an encryption algorithm.  This is the text that a person might want to have encrypted. The output of the encryption algorithm is called ciphertext and is and obscured version of the plaintext.  The algorithm uses a key, which is a code used to encrypt the plaintext into cipher text.  In the same way that a (physical) key can lock and unlock a deadbolt, so can a (electronic) key lock (i.e. encrypt) and unlock (i.e. decrypt) a plaintext message.

In cryptography, a Caesar cipher, is one of the simplest and most widely-known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions further down the alphabet. For example, with a shift of 3, A would be replaced by D, B would become E, and so on. The method is named after Julius Caesar, who used it to communicate with his generals.

For this homework, we will only encrypt letters; numbers and punctuation will not be encrypted.

As an example, with a shift, or key, of 3, the text 'hello' would encrypt to 'khoor', as 'k' is 3 letters beyond 'h', 'h' is three letters beyond 'e', etc.  With a key of 13, 'world' would encrypt to 'jbeyq'.  You can play around with an online Caesar cipher here.

Part I: The standard Caesar Cipher methods

There are four methods that you will need to implement in this part of the homework.

Method main()

main(): the main method should provide a menu of choices, and read in a single integer.  The value of that integer will determine what the program will do: 1 is encrypt plain text, 2 is decrypt ciphertext, and 3 is crack ciphertext (described in part II, below).  Any other value should cause the program to exit.

Note that any run of your program should only take in 2 or 3 inputs: the first is always the integer described above.  For values of 1 and 2, the other two inputs will be (in order) the key, and the text.  For a value of 3 (the crack() method), the only remaining input will be the text to be cracked.

All input must be in the main() method, and it must all use a single Scanner object created inside the main() method.  Once the choice is selected (1, 2, or 3), the program should request the appropriate amount of input (possibly a key, and then some text).  Your main() method MUST use nextLine() (not next()) to read in the text to be used in this program.  Note that if the program is not allowing you to enter text after you enter an int, (meaning it reads in an empty string without allowing you to type anything in), try putting in an extra stdin.nextLine() after reading in the int (this is a bug in the Scanner object).

Method encrypt()

This method will encrypt plain text into ciphertext.  It should have the following prototype:

public static String encrypt (int key, String plaintext) {

The method will encrypt the passed plaintext; the result (aka the ciphertext) is then returned from this method.  You will have to go through each letter in the String (using the various String methods we've seen so far), and encrypt each one individually -- these are then combined into the final ciphertext.

Your method should read in no input (as that was done in the main() method), just the two parameters.  It must print the result prior to returning it.

A few hints:

  • It will be easiest to first convert the entire string to lower case (via the toLowerCase() method) -- this way you are not dealing with mixed case letters.
  • Any numbers or punctuation should not be encrypted, and left just as is in the ciphertext.  To find out if a character is a letter, you can use the Character.isLetter() method.

  • Remember that you can do character arithmetic: to find out what 'a' is when encrypted with a key of 3, you can just use 'a'+3.

  • For encrypting, you add the key to the letter -- if the result is greater than 'z', you should subtract 26 from the result.  For decrypting (the next method), you should subtract the key from the letter (and add 26 if it's less than 'a').

Method decrypt()

This method will decrypt a Caesar cipher encoded message.  It should have the following prototype:

public static String decrypt (int key, String ciphertext) {

The method will decrypt the passed ciphertext; the result (aka the plaintext) is then returned from this method.  You will have to go through each letter in the String (using the various String methods we've seen so far), and decrypt each one individually.

This method will do the exact same thing as the encrypt() method, except that it will subtract the key from the letter (instead of adding it).

Your method should read in no input (as that was done in the main() method), just the two parameters.  It must print the result prior to returning it.

Testing

To see if your code works properly, you should first try to encrypt and then decrypt a given message, and make sure it does it right.  There are a number of online Ceasar encrypters and decrypters -- see the end of the Caesar Cipher Wikipedia article for links to some of them.

Here are a few things for you to try to decrypt.  Note that non-letters (spaces and the single quote) are copied as-is to the ciphertext.

  • "gduwk ydghu lv oxnh vnbzdonhu'v idwkhu" (key is 3)
  • "v fnirq n ybg ba zl nhgb vafhenapr ol fjvgpuvat gb trvxb" (key is 13)

Part II: Problems with the Caesar Cipher

The Caesar Cipher is useful in some situations -- and it was never cracked in Caesar's time.  But that doesn't work so well today.  It turns out that it is very easy to crack a Caesar Cipher.  There are a couple of ways to do this.  Since there are only 26 possible keys (and the key of 0 -- or 26 -- is not going to be used, as then the plain text would be the exact same as the ciphertext), you can simply try all 25 possibilities, and see which one looks like English.  We'll try another method here, though.

Consider the following ciphertext:

ymjwj nx f ymjtwd bmnhm xyfyjx ymfy nk jajw fsdgtid inxhtajwx jcfhyqd bmfy ymj zsnajwxj nx ktw fsi bmd ny nx mjwj, ny bnqq nsxyfsyqd inxfuujfw fsi gj wjuqfhji gd xtrjymnsl jajs rtwj gnefwwj fsi nsjcuqnhfgqj. ymjwj nx fstymjw ymjtwd bmnhm xyfyjx ymfy ymnx mfx fqwjfid mfuujsji.

If you analyzed the frequency of the various characters in the cipher text, you will notice that the character 'j' appears the most (32 times, in fact), followed by 'f' and 'y' (22 times each).  In English, the character 'e' is the most common character by far.  Therefore, it is safe to guess that the character 'j' is the ciphertext for the character 'e'.  This means the key is 5, as a "shift" of 3 will convert an 'e' into a 'j' (and back into an 'e').  We will be implementing this algorithm for cracking a Caesar Cipher.

Note, however, that while large sections of English text will most often have the letter 'e' as the most common letter, this will not always be the case, especially for short phrases.  Consider an example from Wikipedia:

This is an unusual paragraph. I'm curious how quickly you can find out what is so unusual about it. It looks so plain you would think nothing was wrong with it! In fact, nothing is wrong with it! It is unusual though. Study it, and think about it, but you still may not find anything odd. But if you work at it a bit, you might find out! Try to do so without any coaching!

This paragraph does not have the e at all (and was especially created to do exactly that).  Such sentences are still crackable, but not by the method we will be using here.  Other ways to crack the Caesar Cipher include focusing on other all letter frequencies (instead of just 'e'), single letter words (which are generally just 'a' and 'i'), word lengths, etc.

Method findMostCommonChar()

This method will take in some text, and find the most common character.  For example, the above text will have 'j' as the most common character.  It must have the following prototype:

public static char findMostCommonChar (String text) {

A few things to keep in mind:

  • To count the letters, first convert the entire string to lower case (via the toLowerCase() method) -- this way you are not dealing with mixed case letters.
  • You only want to count letters -- spaces, punctuation, numbers and such are not counted.

While it is not required, your program should return the lower case character that is the most common (after having converted everything to lower case) -- this will save you a headache later.

There are many ways to count the most common letter (nested loops, a switch statement, arrays, etc.).  Probably the easiest is to use nested loops -- the outer loop goes through each letter, the inner loop goes through each letter in the string.

Method crack()

The last method you will be writing will crack the encryption of a Caesar Cipher.  You can assume, for the sake of this homework, that whatever ciphertext we will be testing your code on, the plaintext version will have 'e' as the most common letter.  The method must have the following prototype:

public static int crack (String ciphertext) {

It will need to crack a Caesar Cipher encoded message by the above algorithm -- first it must find the most common letter (via the findMostCommonChar() method), then print that out, and then figure out the key from the difference between that letter and 'e'.  This method only returns the key, although it must call the decrypt() method (with the newly discovered key) to print out the plaintext.

Keep in mind that you can test your method using the cipher text at the beginning of this section (the one that starts with 'ymjwj...').  Note that you can write a dummy findMostCommonChar() method that just returns 'j', if you are using the above ciphertext to crack.  This is ONLY to test this method -- you need to have a fully working findMostCommonChar() method when you turn in the homework.

Where to Start

This homework will be much easier if you work through it one method at a time.  Write the first method, and then sufficiently test it in your main() method.  Then write the second method, and sufficiently test it in your main() method.  This will make the entire homework much easier, and it will take much less time to complete.

Testing, Good Programming Practices, etc.

The good programming practices from HW 1 need to be in this homework as well. 

You must also show proof of testing.  The reason we do this is that we want to ensure that you have tested your program.  Just showing that it compiles does not mean it works properly!  You should run your programs a few times, testing each of the functionality, and verifying that it works properly (via checking the result on one of the online Caesar cipher links, etc.).  Keep in mind that you can copy all the text in the output window as described at the end of lab 4.  And you can comment out a large section by putting a /* at the beginning and a */ at the end, as discussed in lecture.

Submission

When you are finished, submit the CaesarCipher.java file.

spacer.gif
spacer.gif footer-middle.gif spacer.gif