From 588507bcf5fa4cd7a3baf4be10713833d5a9eca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Fri, 15 Oct 2021 16:10:44 +0200 Subject: [PATCH] #4: Implementing Multiplikative Chiffre --- chapter_one/Multiplikative_Chiffre.py | 65 +++++++++++++++++++++++++++ chapter_one/__init__.py | 0 utils/AlphabetUtils.py | 7 +-- 3 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 chapter_one/Multiplikative_Chiffre.py create mode 100644 chapter_one/__init__.py diff --git a/chapter_one/Multiplikative_Chiffre.py b/chapter_one/Multiplikative_Chiffre.py new file mode 100644 index 0000000..5157422 --- /dev/null +++ b/chapter_one/Multiplikative_Chiffre.py @@ -0,0 +1,65 @@ +from utils import AlphabetUtils as au + +ALLOWED_KEYS = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25] + + +def encrypt_text(key: int = 11, cleartext: str = 'BonkRocks'): + """ + Encrypts the given text with the given key + :param key: The key to use. Has to be between 1 and 25 and a coprime to 26. + :param cleartext: The text to encrypt + :return: The encrypted text + """ + # Key has to be coprime to 26 + if key not in ALLOWED_KEYS: + raise AttributeError + + resulting = '' + + for char in cleartext: + index = au.get_index_of_letter(char) + newIndex = (index * key) % 26 + resulting += au.get_letter_at_index(newIndex) + + return resulting + + +def decrypt_text(key: int = 11, ciphertext: str = 'lyngfywgq'): + """ + Decrypts the given ciphertext with the given key + :param key: The key to use. Has to be between 1 and 25 and a coprime to 26. + :param ciphertext: The text to decrypt + :return: The decrypted text + """ + # Key has to be coprime to 26 + if key not in ALLOWED_KEYS: + raise AttributeError + + decrypt_key = _get_key_reverse(key) + + resulting = '' + + for char in ciphertext: + index = au.get_index_of_letter(char) + newIndex = (index * decrypt_key) % 26 + resulting += au.get_letter_at_index(newIndex) + + return resulting + + +def _get_key_reverse(key: int): + """ + Calculates the decryption key (inverse of the original key) based on the following formula: + s * s' mod 26 = 1 + + :param key: The key to reverse + :return: The decryption key + """ + for possibility in ALLOWED_KEYS: + if (key * possibility) % 26 == 1: + return possibility + + +if __name__ == '__main__': + print(encrypt_text()) + print(decrypt_text()) diff --git a/chapter_one/__init__.py b/chapter_one/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/AlphabetUtils.py b/utils/AlphabetUtils.py index bc2d099..045556a 100644 --- a/utils/AlphabetUtils.py +++ b/utils/AlphabetUtils.py @@ -8,14 +8,9 @@ def get_letter_at_index(idx: int, capital: bool = False): return LETTERS[idx] if capital else LETTERS[idx].lower() + def get_index_of_letter(letter: str): if letter.upper() not in LETTERS: raise AttributeError return LETTERS.index(letter.upper()) - - -if __name__ == '__main__': - print(get_letter_at_index(25, True)) - print(get_index_of_letter('รค')) -