Coding The Caesar Cipher – The Caesar Cipher is one of the simplest, and oldest, systems for cryptography.
Let’s see how the Caesar Cipher can be implemented very simply in Python.
One of the simplest methods to create secret messages is undoubtedly the Caesar Cipher. As you might expect, it’s named after Julius Caesar, who used it in his correspondence.
To encipher a message, we choose a whole number and shift every letter down the alphabet by that number of places.
For example, if we choose 3 then B becomes E, M becomes P, and Y becomes B; after Z we start at A again.
To decipher the message, we just shift the letters back again.
ABCDEFGHIJKLMNOPQRSTUVWXYZ : Plain
DEFGHIJKLMNOPQRSTUVWXYZABC : Cipher
Modular Arithmetic and ASCII Codes in Python
To code this in Python, we’ll use remainders.
If we number the letters from 0 to 25 (always count from 0 in Computer Science!), then we just add the shift factor. If we then take the remainder after dividing by 26, 26 becomes 0, 27 becomes 1 and so on, meaning that A comes after Z.
In Python we can turn a letter into a number using the ord() function, which produces the ASCII code corresponding to a letter.
Unfortunately, the ord() Python function doesn’t give a number between 0 and 25. Upper-case letters are between 65 and 90, while lower case letters are between 97 and 122. The other numbers are for punctuation, control characters, and so on.
To deal with this, we can employ a nice trick called conjugation. We move our numbers back to start at zero, perform the shift, then move forward again. Finally, we convert back to a letter using the chr() Python function.
See the short Python program to accomplish this.
Python Code to Implement a Caesar Cipher
plainText = input("Enter your text:\n")
shift = int(input("Enter how many places
to shift:\n"))
cipherText = ""
for char in plainText:
pos = ord(char)
if 48<= pos<= 57:
newpos = (pos-48+shift)%10+48
elif 65<=pos<= 90:
newpos = (pos-65+shift)%26+65
elif 97<=pos<=122:
newpos = (pos-97+shift)%26+97
else:
newpos = pos
cipherText += chr(newpos)
print("Coded Message:")
print(cipherText)
Working with Files in Python
Those who know a little more Python might like to adapt this to take input from a text file and output to another text file.
This lets you encipher a whole letter or even a book in a single pass. I like to set this challenge at Christmas and give my students a copy of Charles Dickens’ “A Christmas Carol” from the Project Gutenberg Project: has text files of many classic out of copyright classic books, in several languages.
Cracking Caesar Cipher Code
This method of creating secret messages is not very secure. Short messages can be deciphered by just applying all 25 possible shifts and reading the output; longer ones can be attacked by a method known as frequency analysis.
The distribution of letters in an average sample of English text has a predictable shape which is easy to determine. The Caesar cipher shift also shifts this distribution, and it is easy to determine the shift by analysing the resultant frequency graph.
We look for the most common letter in the message and assume this must correspond to the most common letter in the English language, e.
This gives us the shift and we can now read the message.
Next issue of Hello World, we’ll look at how to perform frequency analysis on a file.
Mark Thornber has been a maths teacher at Durham Johnston for the last 25 years. Mark has been interested in the mathematical parts of computing since owning his first ZX81.
Originally published in Hello World Issue 1 : The Computing and Digital Making Magazine for Educators. Above article includes modifications from the original article by Mark Thornber. License CC BY-NC-SA 3.0
A more modern way to do this, which is also reasonably easy to read, is with string translations. These are high performance and flexible. You only have to build the mapping once and it will automatically iterate over each character when you translate it.
plainText = input("\nEnter your text: ")
shift = int(input("How many places to shift: "))
lowerAlpha = "abcdefghijklmnopqrstuvwxyz"
upperAlpha = lowerAlpha.upper()
numbers = "0123456789"
before = lowerAlpha + upperAlpha + numbers
after = lowerAlpha[shift:] + lowerAlpha[:shift] + \
upperAlpha[shift:] + upperAlpha[:shift] + \
numbers[shift:] + numbers[:shift]
translation = str.maketrans(before, after)
cipherText = plainText.translate(translation)
print("\nCoded Message: {}".format(cipherText))
print("\nFrom: {}".format(before))
print(" To: {}\n".format(after))
A more modern way