2021-10-15 14:40:23 +00:00
|
|
|
from utils import AlphabetUtils as au
|
|
|
|
|
|
|
|
ALLOWED_KEYS = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
|
|
|
|
|
|
|
|
|
2021-10-15 15:25:08 +00:00
|
|
|
def encrypt_text(cleartext: str, key1: int, key2: int):
|
2021-10-15 14:40:23 +00:00
|
|
|
"""
|
|
|
|
Encrypts the given text with the given keys
|
2021-10-15 15:25:08 +00:00
|
|
|
:param cleartext: The text to encrypt
|
2021-10-15 14:40:23 +00:00
|
|
|
:param key1: The first key. Has to be between 1 and 25 and a coprime to 26
|
|
|
|
:param key2: The second key. Has to be between 0 and 26
|
|
|
|
:return: The encrypted text
|
|
|
|
"""
|
|
|
|
# key1 has to be coprime to 26
|
|
|
|
if key1 not in ALLOWED_KEYS:
|
|
|
|
raise AttributeError
|
|
|
|
|
|
|
|
# key2 has to be between 0 and 25
|
|
|
|
if key2 < 0 or key2 > 25:
|
|
|
|
raise AttributeError
|
|
|
|
|
|
|
|
resulting = ''
|
|
|
|
|
|
|
|
for char in cleartext:
|
|
|
|
index = au.get_index_of_letter(char)
|
|
|
|
newIndex = (index * key1 + key2) % 26
|
|
|
|
resulting += au.get_letter_at_index(newIndex)
|
|
|
|
|
|
|
|
return resulting
|
|
|
|
|
|
|
|
|
2021-10-15 15:25:08 +00:00
|
|
|
def decrypt_text(ciphertext: str, key1: int, key2: int):
|
2021-10-15 14:40:23 +00:00
|
|
|
"""
|
|
|
|
Decrypts the given ciphertext with the given keys
|
2021-10-15 15:25:08 +00:00
|
|
|
:param ciphertext: The text to decrypt
|
2021-10-15 14:40:23 +00:00
|
|
|
:param key1: The first key. Has to be between 1 and 25 and a coprime to 26
|
|
|
|
:param key2: The second key. Has to be between 0 and 26
|
|
|
|
:return: The decrypted text
|
|
|
|
"""
|
|
|
|
# key1 has to be coprime to 26
|
|
|
|
if key1 not in ALLOWED_KEYS:
|
|
|
|
raise AttributeError
|
|
|
|
|
|
|
|
# key2 has to be between 0 and 25
|
|
|
|
if key2 < 0 or key2 > 25:
|
|
|
|
raise AttributeError
|
|
|
|
|
|
|
|
decrypt_key1 = _get_key_reverse(key1)
|
|
|
|
|
|
|
|
resulting = ''
|
|
|
|
|
|
|
|
for char in ciphertext:
|
|
|
|
index = au.get_index_of_letter(char)
|
|
|
|
newIndex = ((index - key2) * decrypt_key1) % 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__':
|
2021-10-15 15:25:08 +00:00
|
|
|
print(encrypt_text('BonkRocks', 11, 7))
|
|
|
|
print(decrypt_text('sfunmfdnx', 11, 7))
|