Created
February 17, 2017 15:55
-
-
Save thcipriani/9a43403cd36510733673ccc0ae01fd3f to your computer and use it in GitHub Desktop.
Simple python implementation of the Vigenère Cipher as described by https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher#Description
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Vigenère Cipher | |
=============== | |
This is a slightly more complicated version of the classic Ceaser cipher (A.K.A | |
Rot13). Rather than rotate each letter of the alphabet 13 characters, we rotate | |
each letter of a message by the offset of the cooresponding letter of a | |
variable length key. | |
This was originally described by making a decryption table where each column in | |
the table (columns A-Z) corresponded to a different offset (i.e., rotation) of | |
the letters A-Z. That is, column 'A' would be 'abcdefghijklmnopqrstuvwxyz' and | |
column 'B' would be 'bcdefghijklmnopqrstuvwxyza' and so forth. Likewise, the | |
decryption table contains rows A-Z. To encrypt a message, you look up each | |
letter of the message in the column head of the description table (again, A-Z) | |
and find he corresponding key letter in the row head of the description table | |
(again, A-Z). | |
For example, the letter 'A' with the key 'Z' corresponds to the letter in | |
column 'A', row 'Z', which would be 'Z'. The letter 'B' with the key 'Z' would | |
correspond to the letter in column 'B', row 'Z', which would be 'Y' and so | |
forth. | |
As always, see Wikipedia for more information [0]. | |
[0] <https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher#Description> | |
""" | |
import string | |
import itertools | |
def encrypt_letter(letter, cipher): | |
"""Rotate an ascii letter by a cipher offset.""" | |
alphabet = string.ascii_uppercase | |
shift = alphabet.find(cipher.upper()) | |
new_alphabet = alphabet[shift:] + alphabet[:shift] | |
table = bytes.maketrans( | |
bytes(alphabet, 'ascii'), bytes(new_alphabet, 'ascii')) | |
return letter.upper().translate(table).upper() | |
def cipher_list(plaintext, key): | |
"""Create tuples of message letter and key letters.""" | |
return list(zip(plaintext, itertools.cycle(key))) | |
def vigenere_cipher(plaintext, key): | |
"""Encrypt plaintext using a key.""" | |
return ''.join([ | |
encrypt_letter(letter, key) | |
for letter, key in cipher_list(plaintext, key) | |
]) | |
if __name__ == '__main__': | |
# The example given on the enwiki page | |
plaintext = 'ATTACKATDAWN' | |
key = 'LEMON' | |
test = 'LXFOPVEFRNHR' | |
ciphertext = vigenere_cipher(plaintext, key) | |
assert(ciphertext == test) | |
print(ciphertext) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment