 Shared171 / Crypto / shift_cipher.ipynbOpen in CoCalc
Author: Hunter Johnson
Description: Some exercises in basic cryptography

## The Caesar Cipher

An ancient form of cryptography is to encrypt a message by "rotating" the alphabet forward by three places.

For example to encrypt a message M = ATTACKATDAWN, each letter will be replaced by the letter that comes three places later.

That is, $A \to D, B \to E, C \to F,...,W \to A, X \to B, Z \to C$.

In the cells below, use Python to encrypt M using the Caesar cipher.

In order to help, I have created a dictionary that might be useful.

# We can make a codebook for our Caesar cipher using a dictionary
codebook = {'A':'D','B':'E','C':'F','D':'G','E':'H','F':'I','G':'J','H':'K','I':'L','J':'M','K':'N','L':'O','M':'P','N':'Q','O':'R','P':'S','Q':'T','R':'U','S':'V','T':'W','U':'X','V':'Y','W':'Z','X':'A','Y':'B','Z':'C'}

# Use the codebook to encrypt the following message.

M = 'ATTACKATDAWN'
C = ''
for m in M:
m_encrypted = codebook[m]
C += m_encrypted
C

'DWWDFNDWGDZQ'
# Exercise:

# Encrypt your own name using the Caesar cipher

# Write your solution here



## As a function ...

Now define a function called caesar_encrypt(M) which takes a message M (assumed to be only uppercase Roman letters) and returns the ciphertext resulting from applying the Caesar cipher to M

# Please define the function here

# Solution:

def caesar_encrypt(M,codebook = codebook):
C = ''
for m in M:
m_encrypted = codebook[m]
C += m_encrypted
return C

#More generally the Caesar cipher is just a certain substitution cipher...

def substitute(M,codebook):
"""
Every character in the string M
is replaced with its encoding codebook[m]
"""
C = ''
for m in M:
m_encoded = codebook[m]
C += m_encoded
return C

caesar_encrypt(M)  #This should encrypt M now that you've defined the function.

'DWWDFNDWGDZQ'

## Decryption

We will now make a new dictionary which is the inverse of the codebook and use it for decryption.

In the cell below, make a new dictionary decodebook which decrypts your encryption of M back to the original message.

# Write your decryption dictionary here.  Try to define it using code, not by hand.
decodebook = dict()
#want decodebook[a]==b  if and only if codebook[b] == a

#  because codebook['A']=='D',  we want decodebook['D']=='A'

#Strategy:  iterate over codebook.items() make decodebook have the opposite entries

# Solution:
for key,value in codebook.items():
decodebook[value] = key

decodebook.items()


dict_items([('D', 'A'), ('E', 'B'), ('F', 'C'), ('G', 'D'), ('H', 'E'), ('I', 'F'), ('J', 'G'), ('K', 'H'), ('L', 'I'), ('M', 'J'), ('N', 'K'), ('O', 'L'), ('P', 'M'), ('Q', 'N'), ('R', 'O'), ('S', 'P'), ('T', 'Q'), ('U', 'R'), ('V', 'S'), ('W', 'T'), ('X', 'U'), ('Y', 'V'), ('Z', 'W'), ('A', 'X'), ('B', 'Y'), ('C', 'Z')])

## Decrypting a real message

Your spies intercept the ciphertext message C = 'PHHWDWWKHWRZHUEHIRUHOXQFK', sent by Caesar.

What is the original message?

# Find the original message here.
substitute(C,decodebook)

'ATTACKATDAWN'
C = 'PHHWDWWKHWRZHUEHIRUHOXQFK'
substitute(C,decodebook)


'MEETATTHETOWERBEFORELUNCH'