alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def shift_cipher(plaintext, key):
"""Apply shift cipher to plaintext,
shifting each letter by key places in alphabet"""
ciphertext = []
for i in range(len(plaintext)):
place_alpha = alphabet.find(plaintext[i])
shifted_place = (place_alpha + key) % 26
ciphertext.append(alphabet[shifted_place])
return ciphertext
"".join(shift_cipher("ATTACKATDAWNZ", 3))
# Vigenere cipher
# now key will be a list of numbers
# This cipher still has some weakness, since there is still some correlation of letters that persists
def vig_cipher(plaintext, key):
"""Apply vigenere cipher to plaintext, shifting letter i by key[i % length(key)] places """
ciphertext = []
for i in range(len(plaintext)):
place_alpha = alphabet.find(plaintext[i])
shifted_place = \
(place_alpha + key[i % len(key)]) % 26
ciphertext.append(alphabet[shifted_place])
return "".join(ciphertext)
vig_cipher("ATTACKATDAWNZ", [3,1,5,25])
# to decode, use negative of encoding key
vig_cipher('DUYZFLFSGBBMC', [-3,-1,-5,-25])
# applying vig_cipher twice
vig_cipher(vig_cipher("ATTACKATDAWNZ", [3,1,5,25]),\
[2,5,7,4])
# decoding the encryption from above
vig_cipher(vig_cipher('FZFDHQMWIGIQE',[-2,-5,-7,-4])\
,[-3,-1,-5,-25])
# the double enciphering done above is equivalent to single enciphering with key the sum of the two keys
vig_cipher("ATTACKATDAWNZ",[5,6,12,29])
# double enciphering with two different key lengths is better
vig_cipher(vig_cipher("ATTACKATDAWNZ", [3,1,5,25]),[2,5,7,4,5])
# one-time pad = vigenere cipher with key length equal to
# message length
# This encryption system is completely secure (information theoretically secure),
# provided that the same key is never used to encrypt two messages (hence "one-time")
def one_time_pad(plaintext, key):
"""Shifts character at plaintext[i] by key[i] places. Key must be at least as long as plaintext"""
if (len(plaintext) > len(key)):
print("Error: key size is too small")
return
ciphertext = []
for i in range(len(plaintext)):
place_alpha = alphabet.find(plaintext[i])
shifted_place = (place_alpha + key[i]) % 26
ciphertext.append(alphabet[shifted_place])
return "".join(ciphertext)
one_time_pad("DANA",[5,6,12,29])
# now encrypt a different message with the same key
one_time_pad("FILE",[5,6,12,29])
# concatenating the above two one-time pad ciphertexts is same as
# concatenating the two plaintexts and applying vig_cipher with same key
vig_cipher("DANAFILE", [5,6,12,29])