Day 18: Cryptography
Imagine Alice wants to send a secret message to Bob, without Eve knowing what the message says. Alice first picks a key, which will be a number such as 3. Alice then tells Bob the key.
Whenever Alice wants to write a message, all she needs to do is shift each of the letters in her message forward in the alphabet by 3 places
So the plaintext: Meet me at the park at three
becomes the ciphertext: Phhw ph dw wkh sdun dw wkuhh
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def generate_otp(sheets, length):
def generate_otp(sheets, length):
for sheet in range(sheets):
with open("otp" + str(sheet) + ".txt","w") as f:
for i in range(length):
f.write(str(randint(0,26))+"\n")
def load_sheet(filename): with open(filename, "r") as f: contents = f.read().splitlines() return contents
sheet = load_sheet('otp0.txt')
print(sheet)
The next function asks the user to type in the message that will be encrypted, and it converts all letters to lowercase
def get_plain_text():
plain_text = input('Please type your message ')
return plain_text.lower()
Now you'll need two functions to open messages written to you, and saving the encrypted messages
def load_file(filename):
with open(filename, "r") as f:
contents = f.read()
return contents
def save_file(filename, data):
with open(filename, 'w') as f:
f.write(data)
def encrypt(plaintext, sheet): ciphertext = ''
def encrypt(plaintext, sheet):
ciphertext = ''
for position, character in enumerate(plaintext):
if character not in ALPHABET:
ciphertext += character
def encrypt(plaintext, sheet):
ciphertext = ''
for position, character in enumerate(plaintext):
if character not in ALPHABET:
ciphertext += character
else:
encrypted = (ALPHABET.index(character)
+ int(sheet[position])) % 26
ciphertext += ALPHABET[encrypted]
return ciphertext
Save and test your function with:
sheet = load_sheet('otp0.txt') print(encrypt('This is a secret message.', sheet))
def decrypt(ciphertext, sheet):
plaintext = ''
for position, character in enumerate(ciphertext):
if character not in ALPHABET:
plaintext += character
else:
decrypted = (ALPHABET.index(character)
- int(sheet[position])) % 26
plaintext += ALPHABET[decrypted]
return plaintext
Decrypting the message is similar to encrypting it. The only difference is you subtract the value rather than add it.
Save and test your function with:
sheet = load_sheet('otp0.txt') ciphertext = encrypt('Nobody can read this', sheet) print(ciphertext) print(decrypt(ciphertext, sheet))
def menu():
choices = ['1', '2', '3', '4']
choice = '0'
while True:
while choice not in choices:
print('What would you like to do?')
print('1. Generate one-time pads')
print('2. Encrypt a message')
print('3. Decrypt a message')
print('4. Quit the program')
choice = input('Please type 1, 2, 3 or 4 and press Enter ')
if choice == '1':
sheets = int(input('How many one-time pads
would you like to generate? '))
length = int(input('What will be your maximum
message length? '))
generate_otp(sheets, length)
elif choice == '2':
filename = input('Type in the filename of
the OTP you want to use ')
sheet = load_sheet(filename)
plaintext = get_plaintext()
ciphertext = encrypt(plaintext, sheet)
filename = input('What will be the name
of the encrypted file? ')
save_file(filename, ciphertext)
elif choice == '3':
filename = input('Type in the filename of
the OTP you want to use ')
sheet = load_sheet(filename)
filename = input('Type in the name of the
file to be decrypted ')
ciphertext = load_file(filename)
plaintext = decrypt(ciphertext, sheet)
print('The message reads:')
print('')
print(plaintext)
elif choice == '4':
exit()
choice = '0'
menu()