Caesar Cipher

The Code
The lines in the code were numbered for the purpose of discussion.

1. #THE CAESAR CIPHER
2. #IMPORT MODULE PYPERCLIP
3. import pyperclip
4. #SET CONSTANTS / INITIAL VALUES
5. key = ''
6. availmodes='12'
7. SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !?.,'
8. translated = ''
9. message = ''
10. mode = ''
11. selectmode = ''
12. #MESSAGE TO ENCRYPT/DECRYPT
13. print('\n')
14. print('-----*-----*-----*-----*-----BEGIN')
15. print('Input the message:')
16. message = input()
17. print('Select the mode:\n[1] Encrypt\n[2]Decrypt')
18. selectmode=input()
19. print('Input encryption key (between 1-89):')
20. inputkey=input()
21. print('-----*-----*-----*-----*-----*-----')
22. if selectmode == '1':
23.     mode = 'encrypt'
24. elif selectmode == '2':
25.     mode = 'decrypt'
26. key=int(inputkey)
27. if key ==67:
28.     key=68    
29. if (key >89 ) or (key <1): 
30. #PROMPT IF INVALID KEY IS PROVIDED 
31. print('\nERROR:\n') 
32. print('Invalid key provided. Please select between 1 to 89.') 
33. else: 
34. if selectmode in availmodes: 
35. for symbol in message: 
36. #ONLY SYMBOLS STORED IN THE VARIABLE SYMBOLS CAN BE DECRYPTED 
37. if symbol in SYMBOLS: 
38. symbolIndex = SYMBOLS.find(symbol) 
39. #PERFORM ENCRYPTION/DECRYPTION 
40. if mode == 'encrypt': 
41. translatedIndex = symbolIndex + key 
42. elif mode == 'decrypt': 
43. translatedIndex = symbolIndex - key 
44. #HANDLE WRAP AROUND IF NEEDED 
45. if translatedIndex >= len(SYMBOLS):
46.                     translatedIndex = translatedIndex -len(SYMBOLS)
47.                 elif translatedIndex < 0:
48.                     translatedIndex = translatedIndex + len(SYMBOLS)
49.                 translated = translated + SYMBOLS[translatedIndex]
50.             else:
51.#APPEND THE SYMBOL WITHOUT ENCRYPTING OR DECRYPTING
52.                 translated = translated + symbol
53.#OUTPUT THE TRANSLATED STRING
54.         if selectmode == '1':
55.             print('Encrypted Message: ' + translated)
56.         elif selectmode == '2':
57.            print('Decrypted Message: ' + translated)    
58.         pyperclip.copy(translated)
59.     else:
60.         #PROMPT IF INVALID MODE IS SELECTED
61.         print('\nERROR:\n')
62.         print('Invalid mode selected.')
63. print('-----*-----*-----*-----*-----END')

Sample Output

 

Module Importation

Modules are python programs that contain additional functions not included in the built ins. Line #3 is an example of importing a module to your code.

 

Constants, Variables and Symbols

Constants are also variables, but their values should not change while the program is not running. A symbol is a cryptography term for a single character that a cipher can encrypt or decrypt, while a symbol set is every possible character that a cipher can encrypt or decrypt. In this particular program, the symbol set is the constant named SYMBOL.
SYMBOL is in upper case because it is a constant. This is not a requirement but a good practice.

Line #7 is an example of a constant that will contain a fixed value. It will not get change unless you add a code below it that will deliberately change its value.

 

for Loop Statement

Line #35 – the for statement simply means that for each character or symbol in the variable message, run these commands below.

For Loop is made up of the following:

  • The for keyword
  • A variable name
  • The in keyword
  • A string or variable containing a string
  • A colon

 

The if Statement

Line #37 says ‘if symbol in SYMBOLS’. Since we entered the for loop, which examines each character inside the variable message. The if statement examines if each character in message matches the characters in the constant SYMBOLS. Basically, it tests if the symbol is found in the symbol set.

 

The elif Statement (else if)

The elif statement is paired with an if statement if there is another condition that needs to be met before the block of codes will be executed. If the statement in elif is not met, the block of code will not be executed.

 

The find() String Method

Line #38 – symbolIndex = SYMBOLS.find(symbol). The find method here is attached to the variable symbol, which at each cycle of loop contains one character of the message.

Methods are just like functions except they’re attached to a value with a period (attached to a variable containing a value. In Line #38 find() method returns the index number of the character contained in symbol from the constant SYMBOLS. Index starts with zero, so:

SYMBOLS = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !?.,’

The letter j in SYMBOLS is the 36th character, but since find solves for index, the returned value is 35

Find method is case sensitive, so finding a lower case letter from a variable that only contains its upper case equivalent will not be able to find anything. If character being searched is not found, the returned value is negative one (-1).

The string you pass as an argument to the find() method can be more than one character. The index that will be returned by find shall be the index of the first character that was found.

 

Performing the Encryption and Decryption

The index number found by the method find() is stored in the variable symbolIndex. The value of the key variable is added to the value of symbolIndex to encrypt or subtracted to decrypt.

Line #41: translatedIndex = symbolIndex + key

This means that the index assigned to translated is symbolIndex plus the value of the key.

The image below shows the index equivalent of SYMBOLS and the original message.

So, if we are the add the value of the key for each index (where in this example key = 13), we will be able to obtain the following result:

 

Handling Wrap Around

if translatedIndex >= len(SYMBOLS):
translatedIndex = translatedIndex -len(SYMBOLS)
elif translatedIndex < 0:
translatedIndex = translatedIndex + len(SYMBOLS)

If the value of the translatedIndex is greater than or equal to the total characters inside SYMBOLS, the total length of SYMBOLS will be deducted from translatedIndex.

For example, the character comma (,) – it’s index value in SYMBOLS is 66, plus 13 = 79.

A translatedIndex of 79 will cause translatedIndex = translatedIndex -len(SYMBOLS) to be executed. So, 79 – 67 = 12, which is equivalent to M. Basically, the program will go back to index zero and continue counting if the translatedIndex is already equal or greater than the total number of symbols.