👾
Sarel.tech
  • Home
  • 🤓Portfolio
    • Tutorials
      • Python
        • Caesar Cipher in Python
    • TryHackMe Write-ups
      • Pickle Rick
      • Net Sec Challenge
    • Cybersecurity
      • Jump Server with PAM
    • Creativity
      • Catholic Cambodia
      • Shimbukai Karate
      • Pink Cube in Desert
  • 👨‍💻Blog
    • On IT
      • ChatGPT
    • On Management
      • Harvard Certificate in School Management and Leadership (CSML)
    • On Cybersecurity
      • NIST CSF2 Guide for K12 schools
        • Govern (GV)
      • BAE CTF 2024
      • Gamifying Cybersecurity Awareness
Powered by GitBook
On this page
  • What is a Caesar cipher?
  • Requirements
  • Explanation
  • How does it work?
  • Using the Modulo operator
  • Creating the cipher tool
  • The plan
  • The sub-problems
  • Getting input from the user
  • Converting the capital letters
  • Converting lower case letters
  • Building the secret code
  • Conclusion

Was this helpful?

  1. Portfolio
  2. Tutorials
  3. Python

Caesar Cipher in Python

This page aims to outline how to create a Ceasar cipher in Python. It is primarily to help my students, but hopefully it can help other people as well.

PreviousPythonNextTryHackMe Write-ups

Last updated 2 years ago

Was this helpful?

What is a Caesar cipher?

A Caesar cipher is an example of a substitution cipher. Essentially, you take the starting phrase and shift each letter of the word or phrase a certain number of spots down the alphabet. Traditionally, Caesar used a shift of 3, but you can also use other numbers.

Caesar Cipher by Wikipedia Commons

In other words, if I use a shift of 5, the word "hello" should return as "mjqqt". With a shift of 2, it will be "ifmmp"

Requirements

In order to create a Caesar cipher tool, it will be useful to know the following functions and concepts. Click on each concept to learn more about it.

Explanation

The core component of the Caesar cipher is the following formula:

for character in phrase:
    chr((ord(character) + shift - i) % 26 + i)

In the above example, i is 65 for uppercase letters and 97 for lowercase letters. That is because the ASCII code for the first letter of the alphabet, A, is 65 for uppercase and 97 for lowercase. The shift variable is how many spaces we want to shift our starting phrase by.

Remember that character, shift, phrase and i are just variable names. You can name your variables whatever you want. For example, instead ofcharacter, you can call it letter, or even something else. Just try to use names that make sense and describe the use of the variable.

The chr() function takes a number and returns the equivalent character according to the ASCII table. For example, chr(70) will return an uppercase F.

The ord() function returns the ASCII number of a character. So ord('B') will return 66.

Practice. Use an ASCII table to find the ASCII codes for the phrase "I like Python".

The correct answer is: 73 32 108 105 107 101 32 80 121 116 104 111 110. Note how even the space has it's own ASCII code (32), and that capital letters have different codes than lower case ones.

How does it work?

Let's assume that we will work with uppercase letters.

First, there is this part:

ord(character)

Since we are running this function in a loop (remember, it's the for character in phrase part), it will get the ord(), or the ASCII code, of each character in that phrase. We will then end up with a sequence of numbers. So if I input the phrase "SAREL", I will get the numbers 83, 65, 82, 69 and 76. By changing these numbers and converting them back into characters, we can get different characters than what we started with! And that is exactly what we will do.

ord(character) + shift

Here, we add the shift amount to our ASCII numbers. In other words, if we use a shift of 3, then 83, 65, 82, 69 and 76 will turn into 86, 68, 85, 72 and 79. If you look up the ASCII table, you will see this corresponds to V, D, U, H and O.

However, here we are introduced to a potential problem. What if the starting phrase has letters near the end of the alphabet? What if we used the word WAX with a shift of 5? WAX would turn into \F] instead of BFC as we expect. So how can we loop around back to the start of the alphabet? With the modulo operator.

Using the Modulo operator

If you have heard of the modulo operator before, you might associate it with checking whether a number is odd or even, or if it is a multiple of another number. However, you can also use the modulo to loop within a range of numbers. If you have never heard of modulo before, it returns the remainder after division, eg. 5 / 2 = 2 remainder 1. So 5 % 2 = 1.

As an example, let's look at a standard, 12-hour clock.

If you start at 5 o'clock and add 5 hours, you will have 10 o'clock. Makes sense, right? 5 + 5 = 10. But what if you start at 9 o'clock? 9 + 5 = 14, but there is no 14 o'clock, there is only 2 o'clock. So how do we get 9 + 5 = 2? By using modulo.

Since there are only 12 hours on a clock, if we take 14 % 12, we will end up with 2.

Let's try with another example. 7 o'clock, and moving on 8 hours.

Let's try with another example. 7 o'clock, and moving on 8 hours.

7 + 8 = 15

15 % 12 = 3. We get 3 o'clock.

Remember, we are using % 12 because there are only 12 hours on a clock face.

Let's try one last, crazy example. 8 o'clock, adding 29 hours!

8 + 29 = 37

37 % 12 = 1. So we will end up at 1 o'clock again.

And this will also work with any number. Let's add a modulo to our first example of 5 + 5.

5 + 5 = 10

10 % 12 = 10. Since 12 can not divide into 10, the entire 10 is given back as a remainder.

We can apply this to the alphabet as well. Or anything else that needs to "loop around".

Take the 23rd letter of the alphabet (W) and add 6 to it.

Take the 23rd letter of the alphabet (W) and add 6 to it.

23 + 6 = 29.

29 % 26 = 3. So we end up with the 3rd letter, or C.

This brings us to the next part of our code.

(ord(character) + shift - 65) % 26 + 65

As you saw above, the modulo trick works because we have a logical place value for our characters, for example, A is 1, B is 2, Z is 26, etc. But the ord() function returns values starting at 65! To fix that, we simply subtract 65 after we do the shift.

So looking at our WAX example, W, A, X first returns 87, 65, 88. Adding a shift of 5 returns 92, 70, 93. Now, when we subtract 65 from those values we will get 27, 5, 28.

Now we use modulo to try and loop each number back so they are less than 26.

27 % 26 = 1.

28 % 26 = 2.

So after applying the modulo we will have 1, 5, and 2. All that is left is to add the 65 that we removed earlier back in order to make them valid ASCII numbers again. So we will get 66, 70, 67. Look them up on the ASCII table and you will see that these numbers correspond to B, F and C.

Lastly, we need to convert these ASCII values of ours back into characters, and we do this with the chr() function.

chr((ord(character) + shift - 65) % 26 + 65)

So we just get the chr() of all of the previous code and that will return the fully shifted character.

Creating the cipher tool

Now that we know how our main algorithm works, let's see how we can build a program that utilizes it.

The plan

We want to create a cipher tool that takes two inputs - a phrase and a key - and returns the secret code. It should look something like this when we are done:

Please enter a phrase: Hello Students!
Please enter a key: 7
Your secret code is:
Olssv Zabkluaz!

As you can see, our cipher tool only converts characters that are part of the alphabet. So things like spaces and punctuation marks are not converted.

So, where do we get started? By breaking down our program into sub-problems, which makes them easier to deal with.

The sub-problems

In order to make our program, we need to solve the following problems:

Breaking our program down into smaller, more manageable problems makes our lives easier. The wonderful thing about programming is that you don't necessarily have to start at the beginning every time.

Getting input from the user

This is likely the easiest step in our program and the rest of our program depends on it, so let's get this out of the way first.

We will get the input two times, and save the results in variables

First try by yourself, and then check the answer.
original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

Remember that anything we get from the input() function returns a string, and for the shift we actually need an integer, so I immediately enclosed the input for shift in an int() function, so we don't need to do that later.

And that's it for gathering the input! Now let's start building our functions.

Converting the capital letters

chr((ord(character) + shift - 65) % 26 + 65)

So let's create a function in which we can use this algorithm every time we come across a capital letter.

Try creating a function that returns the shifted character
def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)

We create a new function with the def keyword. We want to bring two arguments into our function, the character we want to convert and the shift key we want to convert it by. Then we simply return the converted character.

Converting lower case letters

Converting lower case letters is very similar. Our core algorithm is:

chr((ord(character) + shift - 97) % 26 + 97)

See that the only difference is that the 65 is now a 97, because the ASCII code for a lowercase "a" is 97.

If we create a function similar to above it will look like this:

def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

Now we have a function for converting uppercase letters and one for lowercase letters.

Technically, we don't have to create functions for these conversions. However, creating them makes our code more readable and easier to work with.

Building the secret code

This is probably the hardest part of the code. Now we need to take our original_phrase input, go through it one character at a time, determine whether it is uppercase, lowercase or non-alphabet, convert it as needed and then build our new secret code.

Before we continue, I will add one more empty variable called secret_code in which we will store our final result.

So far, our total code looks like this:

original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

Now we will add a for loop that goes over each character in the phrase, checks whether it is part of the alphabet, then checks whether it is uppercase or lowercase so we can call the correct function and finally add the converted character into our secret_code variable.

This one is tricky. Try by yourself first before you check the answer.
for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character

Let's go over each line of the above code and what it does:

  1. We create a for loop that gets each character in our original phrase.

  2. We check if this character is part of the alphabet using the isalpha() function.

  3. If it is part of the alphabet, we check whether it is uppercase with the isupper() function.

  4. We run that character through our uppercase converter and we add the result to the end of our secret code.

  5. If that character is not uppercase

  6. Then run it through our lowercase converter and add it to the end of our final result.

  7. If the character is not part of the alphabet

  8. We simply add it to the end of our final result.

With our for loop done, our code so far looks like this:

original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character

Just one more step left, we add print(secret_code) all the way at the end of our program.

original_phrase = input("Please enter a phrase: ")
shift = int(input("Please enter a key: "))

secret_code = ""

def convert_upper(character, shift):
    return chr((ord(character) + shift - 65) % 26 + 65)
    
def convert_lower(character, shift):
    return chr((ord(character) + shift - 97) % 26 + 97)

for character in original_phrase:
    if character.isalpha() == True:
        if character.isupper() == True:
            secret_code = secret_code + convert_upper(character, shift)
        else:
            secret_code = secret_code + convert_lower(character, shift)
    else:
        secret_code = secret_code + character
        
print(secret_code)

Let's go over each line one by one again.

  1. Asks the user to input a phrase and then saves this phrase in a variable called original_phrase.

  2. Asks the user for a key. We then convert that key to an integer and save it in a variable called shift.

  3. blank

  4. We create a variable called secret_code, and make it an empty string. This is because we will add the converted characters one by one to build our secret code.

  5. blank

  6. We define a function called convert_upper which takes two arguments, character and shift.

  7. This function runs our algorithm and returns the result. We can use this result to do something else.

  8. blank

  9. We create another function called convert_lower, which also takes two arguments, character and shift.

  10. This function runs our algorithm and returns the result. We can use this result to do something else.

  11. blank

  12. This for loop goes over each character in our original phrase, one by one, and then runs the code below on that character.

  13. We check if this character is part of the alphabet using the isalpha() function.

  14. If it is part of the alphabet, we check whether it is uppercase with the isupper() function.

  15. We run that character through our uppercase converter, using the character variable from the loop, and our shift from the input, and we add the result to the end of our secret_code.

  16. If that character is not uppercase

  17. Then run it through our lowercase converter and add it to the end of our final result.

  18. If the character is not part of the alphabet

  19. We simply add it to the end of our final result.

  20. blank

  21. We print the secret code.

Conclusion

And that is it!

This project teaches you a lot of the core skills you need as a beginner programmer in one short exercise. Remember to add comments to your code when doing it on your own so that you don't forget what certain pieces of code do.

Lastly, do me a favour and rate this tutorial at the bottom of the page!

You can read more about it on the or the .

It will also help to have an ASCII table ready, such as .

ASCII Table by Wikipedia Commons

we mentioned that the algorithm for converting capital letters and lowercase letters are a little bit different. For capital letters it is:

Wikipedia page
Simplified Wikipedia page
Variables
Modulo
For loops
If statements
functions
chr()
ord()
isalpha()
isupper()
islower()
What ASCII is
this one
Get input from the user
Convert all capital letters
Convert all lower-case letters
Build the secret code
Earlier
🤓
Page cover image
Clock face by Kiddo Shelter