2010 January 20 / j d a v i s @ c a r l e t o n . e d u

Assignment 5: Ciphers

The purpose of the assignment is to practice with strings, ciphers, and modular arithmetic (%). Specifically, you will write six functions that encipher and decipher strings of text using three different cipher systems. You will assume that the text consists of the 26 uppercase English letters — no lowercase letters, digits, spaces, or punctuation — because this simplifies your code a bit without sacrificing any important ideas. We also discuss good Python style in this assignment.

Download the file ciphers.py; this is the file that you will edit and hand in. You may complete the assignment with one partner, or alone if you prefer. If you want me to find you a partner, then e-mail me. Your work is due Friday at 11:59 PM.

Good Python Style

Examine the file ciphers.py. It displays two elements of good Python style, that you are required to incorporate into all of your Python code for the rest of the course.

First, there are six functions defined in the file. In each function, the first indented line is actually a string wrapped in tripled double quotation marks. This string has no effect on how the function works — why? — but Python uses the string to provide documentation for the function, as follows.

In bash, navigate to where you stored this file (using cd, ls, etc.), launch the Python interpreter (python), and import the file (import ciphers). Then enter help(ciphers.encipherRot13). Python launches its documentation viewer and shows you some text that explains what the encipherRot13() function does. Where did this text come from?

The lesson is this: Whenever you write a function, the first indented line should be a string, wrapped in tripled double quotation marks, that explains precisely what the function does. This is called the function's documentation string or docstring. Python makes the string available in its help system; also, anyone reading your code gets a nice description of the function, right at its start. You are required to supply documentation strings for all functions that you write in this course.

Second, toward the end of the file is a chunk of code that begins with

if __name__ == "__main__":

This line tests whether the file was run directly by the user or imported as a module. If the file was run directly by the user, then this file is the "main" file of the program, and the built-in variable __name__ has the value "__main__" (a string). If the file was imported into another program or into the Python interpreter, as in import ciphers, then __name__ has some other value, such as "ciphers".

Therefore, the code under the if __name__ == "__main__": conditional is executed if the user ran the file directly, but is not executed if the user imported the file to use its functions. We've seen this idiom already, in Assignment 4: Tic Tac Toe. There I gave you a file with some demonstration code under the conditional. The code was not executed when I imported the file into other programs.

The lesson is this: Whenever you write a Python file, include this conditional with some demonstration code under it, that shows how to use your code and what it does. You are required to do so, for all Python files that you write in this course.

Rot13

Our first cipher system is called Rot13. To illustrate it, suppose that your sister is about to go on a long trip to Romania. While she is away, you would like to communicate with her by secret messages. Before she leaves you agree on the Rot13 cipher. One day, while your sister is away, you decide to send her the message "MYBIKEWASSTOLEN".

To encipher the message using Rot13, you simply shift each character in the message 13 spaces to the right in the alphabet. For example, the first character is 'M'. 13 letters to the right of 'M' in the alphabet is 'Z'. Therefore the first character of your enciphered message is 'Z'. It is helpful to view this shifting as a kind of "arithmetic with letters". Namely, 'M' is letter 12 of the alphabet (counting from 0). If you start at letter 12 and shift right by 13 letters, you end up at letter 25, which is 'Z'.

The second character in your original message is 'Y'. But this is at the end of the alphabet; you can't shift it right by 13 letters. We handle this by declaring that the alphabet "wraps around", so that after 'Z' comes 'A', 'B', 'C', and so on. Following this logic, the letter 'L' is 13 letters to the right of 'Y'. Therefore the second character of the enciphered message is 'L'. Even in this case, you can view shifting right by 13 letters as a kind of "arithmetic with letters". The key is to use the modulus operator %. How? Why?

You continue enciphering your message's characters in this same manner, until you've enciphered the entire message as "ZLOVXRJNFFGBYRA".

When your sister receives this enciphered message, she knows that you've enciphered it using Rot13, so she deciphers it. How does that work? In Rot13 there is a particularly simple relationship between enciphering and deciphering; what is it?

In the file ciphers.py, complete the two functions encipherRot13() and decipherRot13(). Hint: The assigned textbook reading helps you figure out where various letters are in the alphabet.

Caesar Cipher

The Caesar cipher is a little more complicated that the Rot13 cipher, because it requires a password. To illustrate it, suppose again that you want to communicate with your sister who is going far away. Before she leaves, you and she agree on a single-character password — say, 'Q'. Then, while she is away, you decide to send her the message "GRANDPASMELLSFUNNY".

You encipher the message by adding the password 'Q' to each character. But what does it mean, to add two characters together? It means that you add their indices in the alphabet. For example, 'G' is letter 6 in the alphabet, and 'Q' is letter 16. So their sum is letter 22, which is 'W'. In short, 'G' + 'Q' = 'W'; this is the first character of the enciphered text. Next you must add 'R' and 'Q'. 'R' is letter 17 and 'Q' is still letter 16, so their sum is letter 33. But the alphabet only goes up to 'Z', which is letter 25. We handle this by again letting the alphabet wrap around; after 'Z' comes 'A', 'B', 'C', etc. Following this logic, letter 33 is 'H'. In short, 'R' + 'Q' = 'H' is the second character of the enciphered text. You continue in this manner, until you have enciphered the entire message as "WHQDTFQICUBBIVKDDO".

Once you've enciphered the message, you send it to your sister, who deciphers it using the same password 'Q' that you used to encipher it. What exactly is the algorithm for deciphering?

In the file ciphers.py, complete the two functions encipherCaesar() and decipherCaesar().

Repeated Pad

Our final cipher system is called the repeated pad. Like the Caesar cipher, this system depends on a password, which for historical reasons is called a pad. As in the Caesar cipher, the two parties communicate using a pad that they've agreed upon ahead of time. However, unlike the pad in the Caesar cipher, the pad in the repeated pad system can consist of more than one character; it really resembles a password that might be used on a modern computer system. (Repeated pads are not actually used in modern cryptography, because they can be deciphered relatively easily. But they are closely related to one-time pads, which have actually been used. We'll discuss those later.)

To illustrate the repeated pad, suppose that you and your sister agree to use the password "LOBSTER". This is your pad. Then, while she is away, you decide to send her the message "IMADECHOCOLATECAKE". To encipher this message, you write the message on a piece of paper, and you write the pad below the message, repeating it until there is one pad character for each message character:

IMADECHOCOLATECAKE
LOBSTERLOBSTERLOBS

Now you add the two lines, character by character, to create the enciphered message. When I say that you add the characters, I mean it just as I did in the previous section. The first character of the enciphered text is 'I' + 'L' = 'T', the second character is 'M' + 'O' = 'A', and so on. The entire enciphered message is "TABVXGYZQPDTXVNOLW".

Once you've enciphered the message, you send it to your sister, who deciphers it using the same pad "LOBSTER". What exactly is the algorithm for deciphering?

In the file ciphers.py, complete the two functions encipherRepeatedPad() and decipherRepeatedPad().

Submit Your Work

Submit your work electronically, as usual. It will be graded according to these criteria:

Questions

Here are some questions to think about. Do not hand these in.