The rotation cipher is often described using a mathematical formula. First, we start by matching each letter in the alphabet to a number as follows:
A = 0, B = 1, C = 2…Z = 25
The plaintext can then be written as a series of numbers:
Plaintext: P Y T H O N
Plaintext as numbers: 15 24 19 7 14 13
If the key is “R” (or 17), we can encrypt the message by adding the corresponding number to each number in the plaintext.
(15 + 17) (24 + 17) (19 + 17) (7 + 17) (14 + 17) (13 + 17)
The problem is that many of these numbers will be greater than 25, which means they will not have a letter to correspond to. Consider, for example, the first letter, which is encrypted as (15 + 17) = 32, which does not correspond to a letter in the alphabet. What we want in this case is for it to go up to Z (25), then loop back around to A (0) and go from there. To do this we use the modulus operator (%). This takes the remainder that you get when you divide two numbers.
(15 + 17) % 26 = 32 % 26 = 6 because 32/26 = 1 remainder 6
So our now our ciphertext becomes:
6 15 10 24 5 4
which corresponds to:
G P K Y F E
To decrypt, all we have to do is take the ciphertext values and subtract the key value, remembering include % 26. This leads to the following encryption and decryption formulas where m represents one letter of plaintext, c represents one letter of ciphertext, and k represents the key.
c := (m + k) % 26
m:= (c – k) % 26
So far, the formula is good for encrypting and decrypting messages for which the alphabet goes from 0 to 25. But in programming, the ASCII values for capital letters start at 65. To account for this, we will add and subtract 65 from the values as follows:
c:= (m – 65 + k) % 26 + 65
m:= (c – 65 – k) % 26 + 65
This essentially brings the values down to the 1-25 range, adds or subtracts the key, calculates the new value, then adds 65 again to put it back into ASCII range.
Programming Activity
Part A
- The goal of this project is to write a Python program that will allow them to set up a Rotation Cipher with any key and use it to encrypt and decrypt any messages.
- Two useful functions they will need are ord() and chr(), which change ASCII values to characters and vice versa. For example, ord(‘A’) will yield 65, and chr(65) will yield ‘A’.
- This project can be good practice for classes and objects. Create a class called RotationCipher that has one instance variable (key) and several methods, including the __init__, setKey for changing the key, encrypt, and decrypt. Discuss with the students what each method should do.
- Note: The formula given for encryption and decryption restricts the possible characters to capital letters. This means that any spaces in the plaintext should be removed before encryption.
- Example Code:
#!/usr/bin/python
class RotationCipher:
def __init__(self, key):
self.key = ord(key) - 65
def setKey(self, key):
self.key = ord(key) - 65
def encrypt(self, message):
encrypted = ""
message = message.replace(" ", "")
for letter in message:
encrypted += chr((ord(letter) - 65 + self.key) % 26 + 65)
return encrypted
def decrypt(self, message):
decrypted = ""
message = message.replace(" ", "")
for letter in message:
decrypted += chr((ord(letter) - 65 - self.key) % 26 + 65)
return decrypted
#This portion is a user interface to interact with the class and methods
RC = RotationCipher("A")
cmd = ""
while cmd != "quit":
cmd = raw_input(">>")
if cmd == "setKey":
key = raw_input("\nKey: ")
RC.setKey(key)
elif cmd == "encrypt":
message = raw_input("\nPlaintext: ")
CT = RC.encrypt(message)
print CT
elif cmd == "decrypt":
ciphertext = raw_input("\nCiphertext: ")
PT = RC.decrypt(ciphertext)
print PT
Part B
- As was mentioned above, the key space for this encryption system is very small (only 26 possibilities in the English alphabet). Even a human, given enough time, would be able to break it by brute-force (for example, using a decoder ring), and a computer could try all 26 possibilities in a very short amount of time.
- The goal of this part is to write a short program to break the cipher. The program should be separate from Part A since someone breaking the cipher should not have access to any of the Rotation Cipher information.
- Discuss with the students how they might go about breaking the cipher, pointing them back to what they did with the decoder rings.
- Give the students a lengthy portion of ciphertext, and ask them to write a program to break it. If they come up with the correct plaintext (and the key), then their code is probably right.
- Example Code:
#!/usr/bin/python
ciphertext = raw_input("Enter the ciphertext: ")
key = 0
ciphertext = ciphertext.replace(" ", "")
while key < 26:
message = ""
for letter in ciphertext:
message += chr((ord(letter) - 65 - key) % 26 + 65)
print message + "\n"
key += 1
