diff --git a/ciphers/playfair_cipher.py b/ciphers/playfair_cipher.py index 7279fb23ecb2..86b45bc4fb6a 100644 --- a/ciphers/playfair_cipher.py +++ b/ciphers/playfair_cipher.py @@ -1,3 +1,24 @@ +""" +https://en.wikipedia.org/wiki/Playfair_cipher#Description + +The Playfair cipher was developed by Charles Wheatstone in 1854 +It's use was heavily promotedby Lord Playfair, hence its name + +Some features of the Playfair cipher are: + +1) It was the first literal diagram substitution cipher +2) It is a manual symmetric encryption technique +3) It is a multiple letter encryption cipher + +The implementation in the code below encodes alphabets only. +It removes spaces, special characters and numbers from the +code. + +Playfair is no longer used by military forces because of known +insecurities and of the advent of automated encryption devices. +This cipher is regarded as insecure since before World War I. +""" + import itertools import string from collections.abc import Generator, Iterable @@ -60,11 +81,26 @@ def generate_table(key: str) -> list[str]: def encode(plaintext: str, key: str) -> str: + """ + Encode the given plaintext using the Playfair cipher. + Takes the plaintext and the key as input and returns the encoded string. + + >>> encode("Hello", "MONARCHY") + 'CFSUPM' + >>> encode("attack on the left flank", "EMERGENCY") + 'DQZSBYFSDZFMFNLOHFDRSG' + >>> encode("Sorry!", "SPECIAL") + 'AVXETX' + >>> encode("Number 1", "NUMBER") + 'UMBENF' + >>> encode("Photosynthesis!", "THE SUN") + 'OEMHQHVCHESUKE' + """ + table = generate_table(key) plaintext = prepare_input(plaintext) ciphertext = "" - # https://en.wikipedia.org/wiki/Playfair_cipher#Description for char1, char2 in chunker(plaintext, 2): row1, col1 = divmod(table.index(char1), 5) row2, col2 = divmod(table.index(char2), 5) @@ -83,10 +119,20 @@ def encode(plaintext: str, key: str) -> str: def decode(ciphertext: str, key: str) -> str: + """ + Decode the input string using the provided key. + + >>> decode("BMZFAZRZDH", "HAZARD") + 'FIREHAZARD' + >>> decode("HNBWBPQT", "AUTOMOBILE") + 'DRIVINGX' + >>> decode("SLYSSAQS", "CASTLE") + 'ATXTACKX' + """ + table = generate_table(key) plaintext = "" - # https://en.wikipedia.org/wiki/Playfair_cipher#Description for char1, char2 in chunker(ciphertext, 2): row1, col1 = divmod(table.index(char1), 5) row2, col2 = divmod(table.index(char2), 5) @@ -102,3 +148,12 @@ def decode(ciphertext: str, key: str) -> str: plaintext += table[row2 * 5 + col1] return plaintext + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + print("Encoded:", encode("BYE AND THANKS", "GREETING")) + print("Decoded:", decode("CXRBANRLBALQ", "GREETING"))