Objectives:
Learn how to use Python to encrypt and decrypt messages
Create a Python program to brute-force the Caesar cipher
Implement the Python fundamentals of building lists and using for loops
You are going use Python to do cryptography, specifically the Caesar cipher. To recap, the Caesar cipher encrypts and decrypts messages by shifting the alphabet. For example, if you wanted to encrypt the message “CYBER CAMP” using a shift of 1, each letter would move one space to the right and result in “DZCFS DBNQ”. Remember using the decoder ring?
Remember how tedious and time-consuming it was to encrypt and decrypt messages by hand? Remember dropping the ring and losing your shift value? Not that you should think of the decoder ring as your enemy, but you can use what you learned from it to create short Python scripts to do all that work for you almost instantly. You will write a script to encrypt messages, to decrypt messages, then to brute-force all decryption combinations (this is handy if you do not know the shift value).
Open up Python 3 (IDLE) and select File, then New File to create a fresh file to write your program. You want to go ahead and select File, Save As… to give your program a unique name that identifies what it does. Your first program will only do encryption, so naming it something like caesar_enc.py should do the trick.
This section teaches the Caesar cipher in code snippets. As new snippets are explained, you will append them to your code to create the full program.
One of the first things any polite program should do is ask the user for any information it needs. Since you are creating an encryption program, you will need an original message, or plaintext, to encrypt.
plaintext = input("Enter the message you would like to encrypt: ") #Line 1
plaintext = plaintext.upper() #Line 2
The code above uses the input() command to get the original message from the user and store it into the plaintext variable. To keep the program simple, it then uses upper() to make the content of plaintext all uppercase.
key = input("Enter the shift value: ") #Line 3
key = int(key) #Line 4
encList = [] #Line 5
Another piece of input needed from the user is a shift amount. Ideally this will be in the range of 1 to 25. A shift of 0 would not change anything, and a shift of 26 or greater would just repeat the same alphabet as 1 to 25. The code above requests the shift amount and stores it in the key variable, then uses int() to transform the string input to an integer. It is very important for the program to realize the key input is an integer number and not a string.
The final line of this snippet also creates encList, an empty encrypted list. The term list is very important in programming because it is a type of changeable data structure that you can use to store all sorts of data. In this case, you will be storing the encrypted characters in this list as they are created. Regular strings are unchangeable in Python, so a list is more suitable to get the job done.
The next code snippet is 10 lines and will take a bit of explaining, but its primary use is to shift each letter by the designated amount to create the encrypted message.
for char in plaintext: #Line 6 (Your very first for loop!)
asciiNum = ord(char) #Line 7
if asciiNum < ord('A') or asciiNum > ord('Z'): #Line 8 - This checks for special characters
encList.append(char) #Line 9
else: #Line 10
asciiNum = asciiNum + key #Line 11 - This is where the shift happens!
if asciiNum > ord('Z'): #Line 12
asciiNum = asciiNum - 26 #Line 13 - If the shift goes out of bounds, wrap around the alphabet.
text = chr(asciiNum) #Line 14
encList.append(text) #Line 15
The for loop shown on the first line is a new, powerful type of loop. In general, the for loop will iterate over every item in a sequence and use that item within the loop. In this scenario, the loop will look at every individual character within the plaintext variable and send it into the loop as the char variable to be changed for encryption. For example, if the plaintext was “HELLO”, this loop would run five times. The variable char would contain H the first time, E the second time, L the third time, etc.
The second line uses the function ord() to return a character’s numerical code. This is in Unicode, but the letters also correspond to the numbers on the ASCII table below. Essentially, this allows you to convert text (like A) to numbers (like 65). This is important because you can shift the number by the amount specified in key, then change it back to a letter. This is how the program will achieve encryption.
The if statement checks if there are any special characters (outside of the alphabet range) in the plaintext message. If so, it will add the special character to the encrypted list, unchanged.
If the if statement does not see a special character, it will enter the else condition and shift the numerical code by adding the key – this is where encryption actually happens. If adding the key takes the number out of bounds, there is another if statement here to make sure it stays within the alphabet. This ensures that Z + 1 equals A and not [.
The last two lines of this snippet convert the numerical code back to a character before adding it to the encrypted list.
Almost done! The final lines of code are here to make the encrypted message presentable.
encrypted = ' '.join(encList) #Line 16
print("The encrypted message is: " + encrypted) #Line 17
The first line joins the encrypted list back into a string. This will improve readability when you print out the encrypted message, which is precisely what the next line does.
Once you get all the code copied, it should look precisely like the code below. Remember, Python is really picky about spaces and punctuation.
plaintext = input("Enter the message you would like encrypt: ") #Line 18
plaintext = plaintext.upper() #Line 19
key = input("Enter the shift value: ") #Line 20
key = int(key) #Line 21
encList = [] #Line 22
If everything goes according to plan, running the script will mirror the output below. You can encrypt any message.
Enter the message you would like to encrypt: Hello World!
Enter the shift value: 5
The encrypted message is: MJQQT BTWQI!
You can also use this website to test your program with different values:
The decryption program will be very similar to the encryption program. The program will still take input from the user,convert the letters to numbers, perform the shift, etc. You will need to make the modifications yourself to create decryption. Before you begin, select File, Save As… and name it something like caesar_dec.py. This will retain your encryption file while copying its contents to the decryption file.
Below is a summary of the modifications you will need to make. The gist of it is this: to decrypt something, you need to do the opposite of what was done to encrypt it.
Line 13: When you encrypted, you shifted to the right. Decryption will instead shift to the left.
Line 14: Encryption was worried the shift might take the value past Z. Decryption is worried the shift might go before A.
Line 15: Change this line to keep the value within bounds of the alphabet.
Presentation: The program now decrypts, it no longer encrypts. Change the variables to reflect this (e.g. change plaintext to ciphertext, encrypted to decrypted)
Note the code below needs the above modifications to perform decryption.
plaintext = input("Enter the message you would like encrypt: ")
plaintext = plaintext.upper()
key = input("Enter the shift value: ")
key = int(key)
encList = []
If everything goes according to plan, running the script will mirror the output below.
Enter the message you would like to decrypt: MJQQT BTWQI!
Enter the shift value: 5
The encrypted message is: HELLO WORLD!
Finally, you will modify the decryption program to be able to decrypt without knowing the key value. The program will test every decryption possibility for the Caesar cipher and generate all 25 decrypted outputs (size of alphabet minus 1).Before you begin, select File, Save As… and name it something like caesar_dec_brute.py.
Again, you will make the necessary changes to do brute-force decryption. In addition to the changes you made in the previous step, you will need to make a few more changes.
Lines 4/5: Get rid of the key. You would not have it in a brute-force attempt.
Line 7: Add another for statement here to iterate through every key. The rest of the code will be within this statement. It should be in the format: for key in range(x,y): where x is the first key and y is the last excluded key.
Line 20: Optionally, add the key value to the print statement. The key value will be an integer that can be converted into a string using the str() function.
Line 21: At the end of the code, add a line to empty the list before the next loop begins (Hint: this line already exists in the code).
Note: the code below needs modifications from the previous step and the above modifications to brute-force.
plaintext = input("Enter the message you would like encrypt: ")
plaintext = plaintext.upper()
key = input("Enter the shift value: ")
key = int(key)
encList = []
If everything goes according to plan, it will mirror the output below.
Enter the message you would like to decrypt: MJQQT BTWQI!
Shift 1: LIPPS ASVPH!
Shift 2: KHOOR ZRUOG!
Shift 3: JGNNQ YQTNF!
Shift 4: TEMMP XPSME!
Shift 5: HELLO WORLD!
Shift 6: GDKKN VNQKC!
Shift 7: FCJJM UMPJB!
Shift 8: EBIIL TLOIA!
Shift 9: DAHHK SKNHZ!
Shift 10: CZGGJ RJMGY!
Shift 11: BYFFI QILFX!
Shift 12: AXEEH PHKEW!
Shift 13: ZWDDG OGJDV!
Shift 14: YVCCF NFICU!
Shift 15: XUBBE MEHBT!
Shift 16: WTAAD LDGAS!
Shift 17: VSZZC KCFZR!
Shift 18: URYYB JBEYQ!
Shift 19: TQXXA IADXP!
Shift 20: SPWWZ HZCWO!
Shift 21: ROVVY GYBVN!
Shift 22: QNUUX FXAUM!
Shift 23: PMTTW EWZTL!
Shift 24: OLSSV DVYSK!
Shift 25: NKRRU CUXRJ!
After you have made the modifications, attempt to brute-force this message:
UMNYLICX LYXCLYWN GCMMCIH
What is the decrypted message?
What is the shift value?
Variable – A variable is structure in programming that stores a value for later use.
String – A variable data type that consists of only characters that intended to be read as text.
Integer - A variable data type that holds whole numbers and can be used for math.
int() – Converts to integer.
If statement – An important structure in programming that only runs a portion of code if a certain condition is satisfied.
Looping – An important structure in programming that runs a portion of code repeatedly as long as a certain condition is satisfied.
input() – Prompts the user to type input for the program.
upper() – Converts to uppercase.
List – A changeable data structure containing a sequence of items.
For loop – Iterates over each item in a sequence.
ord() – Returns a character’s numerical code in Unicode, but it is backwards-compatible with ASCII.
list.append() – Adds an element to a list.
join() – Joins a list into a string.