The Caesar Shift Cypher in Python
By: Chris Webb
Tags: Python, Python Programming, Programming

The Caesar Shift Cypher was named after Julius Caesar and is the simplest method of encypherment possible. It consists of shifting letters along by one or more places, so for example if you use a shift of 1 then A becomes B, B becomes C etc.. To decypher the message you just shift letters in the opposite direction. Clearly it lacks sophistication and can easily be cracked, either by trial and error or, if you have a reasonable length of encrypted text, using frequency analysis.

As a little programming exercise I will code the Caesar Shift Cypher in Python, and in a future post will break it with frequency analysis.

The project consists of the following files which you can clone or download gtom the Github repository.

caesarshiftcypher.py

main.py

This is caesarshiftcypher.py.

The encypher Function

The encypher function takes a piece of text to encypher and the number of letters to shift it by. In principle the shift could be any number (except 0 and 26, which get you nowhere or back where you started respectively) but negative shifts or shifts more than 26 only cycle round to shifts which are equivalent to between 2 and 25. I have therefore restricted shift to this range and anything else raises a ValueError exception.

Having got past the range check we create an empty list to hold the characters of the encyphered text. What we need as an end result is a string but building a potentially lengthy string one character at a time using concatenation is very inefficient. Strings are immutable so concatenation actually involves creating a whole new string each time. To get round this inefficiency I am using a list and appending letters to it; when we’ve finished we can create a string from it using the join method.

Now let’s iterate the plaintext , firstly checking if each character is an actual letter, all other characters being ignored. If so the next line actually does three things: converts the letter to upper case with upper , retrieves the ASCII code with ord , and then adds the shift. The letter is now almost encrypted but we need to check if it has run off the end of the alphabet, ie is more than 90 (Z). If so we subtract 26 to roll round to the beginning of the alphabet. Finally the fully encrypted letter is appended to the list.

At the end of the loop we just return an empty string with the contents of the list added with the join method as mentioned above.

The decypher Function

The decypher function basically undoes the above process but is simpler because we don’t need to check for non-letters. In a real-world situation you would probably want to allow for any character, either ignoring non-letters or raising an exception. However, as this is just a “toy” implementation I have assumed the decypher function is only going to be given a string with upper case letters, as generated by the encypher function.

We still check that shift is within range, and then iterate the letters of the encyphered text, picking up and shifting each letter’s ASCII code. This is rolled round if necessary, and then the decyphered letters are added to the list. They are converted to lower case, following the convention that encrypted text is upper case and plain text or decrypted text is lower case. Finally we just use join again to return the decyphered text.

Trying it Out

Now let’s move on to main.py where we try out the functions shown above.

Firstly we import caesarshiftcypher , and then within main create a string to encypher. The string is the first paragraph of The Pickwick Papers by Charles Dickens. After printing it we throw it at the encypher function and print the result. We then pass that result to decypher (obviously using the same shift) and print out the decyphered text. Note that the two function calls are made in a try block; you might want to try out an invalid shift to check the validation is working.

That’s the code finished so run it with this command:

python3.8 main.py

The output is:

As I mentioned above I will follow this up with an article on cracking the cypher using frequency analysis.