The use of codes (or ciphers) as a means of hiding the meaning of messages traces its roots to ancient history. The first known military use of codes was by Julius Caesar in 50 - 60 B.C. The Caesar cipher specified that each letter in the alphabet would be encoded using the letter three positions later in the alphabet. For example, 'a' would be encoded as 'd', 'b' would be encoded as 'e', 'c' would be encoded as 'f', and so on. The code wraps around at the end of the alphabet, so 'x', 'y' and 'z' would be encoded as 'a', 'b', and 'c', respectively. The complete mapping of letters is shown below.
The Cipher class contains a
partial implementation of the Caesar cipher. The
decode methods can be used to encode and decode lower-case letters
by shifting them three positions in the alphabet. Modify these methods so that
they handle upper-case letters and non-letters as well. An upper-case letter
should be encoded/decoded just like its lower-case equivalent, producing the
corresponding upper-case letter. For example, 'A' should be encoded as 'D'.
Characters that are not letters should be left as is. For example, the encoding of a space
or exclamation mark should be that same character unchanged.
toUpperCase methods from
Character class should be of use here.
Once you have tested your implementation, you may use it in combination with the
Encrypt class. This class uses a
Cipher to encode/decode entire files.
Although the Caesar cipher was effective in its time (when very few people could read at all), its simple pattern of encoding letters seems pretty obvious today. However, it can be generalized to create more effective ciphers. The Caesar cipher is an example of a substitution cipher, a code in which one letter of the alphabet is substituted for another. They key "defghijklmnopqrstuvwxyzabc" defines the letter mapping used by the Caesar cipher. Using a different key, a completely different substitution cipher is defined. For example:
Since there are 26! (or roughly 4 x 1026) different arrangements of the 26 letters in the alphabet, there are 26! different keys and so 26! different substitution ciphers that can be defined.
Cipher class so that it can be used to
implement any substitution cipher, not just the Caesar cipher. The key to the
particular cipher should be a parameter to the constructor. That key should
be stored in a field and then used to encode and decode characters. For example, if the string
"qwertyuiopasdfghjklzxcvbnm" was specified in the constructor of a
object, then that object would encode "Java code" as "Pqcq egrt".
You will also need to modify the
Encrypt class so that it specifies
the substitution key when constructing the
While substitution ciphers are reasonably effective at encoding/decoding messages, they are susceptible to various attacks that make them unworthy for serious encryption. Not all letters are equally likely in text, so the relative frequency of characters in a coded message can provide clues for decoding. For example, 'e' is the most frequently used letter in English text. If the letter 'w' appeared most frequently in a coded message, then one might guess that the substitution cipher maps 'e' to 'w'.
One approach to counter this type of analysis is to add rotation to the cipher. After each letter is encoded, the key is rotated so that the first character is moved to the end. For example, using the Caesar cipher key "defghijklmnopqrstuvwxyzabc", the letter 'a' would be encoded as 'd'. But, after this encoding the key would be rotated to be "efghijklmnopqrstuvwxyzabcd". Thus, if the next letter to be encoded was another 'a', it would get encoded as an 'e' this time.
Cipher class so that it performs a rotation after
each character is encoded/decoded. You should define a private method named
rotate that rotates the key field. Then, this method should be called
decode after a character has been processed.
Once you have completed your modifications, create a rotating substitution cipher with the key "qwertyuiopasdfghjklzxcvbnm" and use it to decode the file unknown.txt. If the decoded file is readable, then you will know that your implementation works as desired.