From 1fc3d753cd25693dd8201902d411d9e3b1a111f0 Mon Sep 17 00:00:00 2001 From: Farzad Hayat Date: Mon, 23 Oct 2023 22:32:45 +1000 Subject: [PATCH 1/3] Fixed bug with key modulus wrapping. Should be wrapping on 256, not 255. --- ciphers/xor_cipher.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index 559036d305c5..4f7c1f93ce45 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -44,7 +44,7 @@ def encrypt(self, content: str, key: int) -> list[str]: key = key or self.__key or 1 # make sure key is an appropriate size - key %= 255 + key %= 256 return [chr(ord(ch) ^ key) for ch in content] @@ -63,7 +63,7 @@ def decrypt(self, content: str, key: int) -> list[str]: key = key or self.__key or 1 # make sure key is an appropriate size - key %= 255 + key %= 256 return [chr(ord(ch) ^ key) for ch in content] @@ -81,9 +81,8 @@ def encrypt_string(self, content: str, key: int = 0) -> str: key = key or self.__key or 1 - # make sure key can be any size - while key > 255: - key -= 255 + # make sure key is an appropriate size + key %= 256 # This will be returned ans = "" @@ -107,9 +106,8 @@ def decrypt_string(self, content: str, key: int = 0) -> str: key = key or self.__key or 1 - # make sure key can be any size - while key > 255: - key -= 255 + # make sure key is an appropriate size + key %= 256 # This will be returned ans = "" @@ -132,6 +130,9 @@ def encrypt_file(self, file: str, key: int = 0) -> bool: assert isinstance(file, str) assert isinstance(key, int) + # make sure key is an appropriate size + key %= 256 + try: with open(file) as fin, open("encrypt.out", "w+") as fout: # actual encrypt-process @@ -156,6 +157,9 @@ def decrypt_file(self, file: str, key: int) -> bool: assert isinstance(file, str) assert isinstance(key, int) + # make sure key is an appropriate size + key %= 256 + try: with open(file) as fin, open("decrypt.out", "w+") as fout: # actual encrypt-process From 957fc038970e2b1d60b0f23850417fa874623133 Mon Sep 17 00:00:00 2001 From: Farzad Hayat Date: Mon, 23 Oct 2023 22:44:20 +1000 Subject: [PATCH 2/3] Fixed bug with incorrect assertion type in decrypt function. --- ciphers/xor_cipher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index 4f7c1f93ce45..7779d475d7a4 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -58,7 +58,7 @@ def decrypt(self, content: str, key: int) -> list[str]: # precondition assert isinstance(key, int) - assert isinstance(content, list) + assert isinstance(content, str) key = key or self.__key or 1 From 9cfeeeff2f8b4b3e71debca02099079caae3e140 Mon Sep 17 00:00:00 2001 From: Farzad Hayat Date: Mon, 23 Oct 2023 23:16:35 +1000 Subject: [PATCH 3/3] Added doctests for 4 out of 6 methods --- ciphers/xor_cipher.py | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index 7779d475d7a4..e30955d41ff1 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -35,6 +35,22 @@ def encrypt(self, content: str, key: int) -> list[str]: output: encrypted string 'content' as a list of chars if key not passed the method uses the key by the constructor. otherwise key = 1 + + Empty list + >>> XORCipher().encrypt("", 5) + [] + + One key + >>> XORCipher().encrypt("hallo welt", 1) + ['i', '`', 'm', 'm', 'n', '!', 'v', 'd', 'm', 'u'] + + Normal key + >>> XORCipher().encrypt("HALLO WELT", 32) + ['h', 'a', 'l', 'l', 'o', '\\x00', 'w', 'e', 'l', 't'] + + Key greater than 255 + >>> XORCipher().encrypt("hallo welt", 256) + ['h', 'a', 'l', 'l', 'o', ' ', 'w', 'e', 'l', 't'] """ # precondition @@ -54,6 +70,22 @@ def decrypt(self, content: str, key: int) -> list[str]: output: decrypted string 'content' as a list of chars if key not passed the method uses the key by the constructor. otherwise key = 1 + + Empty list + >>> XORCipher().decrypt("", 5) + [] + + One key + >>> XORCipher().decrypt("hallo welt", 1) + ['i', '`', 'm', 'm', 'n', '!', 'v', 'd', 'm', 'u'] + + Normal key + >>> XORCipher().decrypt("HALLO WELT", 32) + ['h', 'a', 'l', 'l', 'o', '\\x00', 'w', 'e', 'l', 't'] + + Key greater than 255 + >>> XORCipher().decrypt("hallo welt", 256) + ['h', 'a', 'l', 'l', 'o', ' ', 'w', 'e', 'l', 't'] """ # precondition @@ -73,6 +105,22 @@ def encrypt_string(self, content: str, key: int = 0) -> str: output: encrypted string 'content' if key not passed the method uses the key by the constructor. otherwise key = 1 + + Empty list + >>> XORCipher().encrypt_string("", 5) + '' + + One key + >>> XORCipher().encrypt_string("hallo welt", 1) + 'i`mmn!vdmu' + + Normal key + >>> XORCipher().encrypt_string("HALLO WELT", 32) + 'hallo\\x00welt' + + Key greater than 255 + >>> XORCipher().encrypt_string("hallo welt", 256) + 'hallo welt' """ # precondition @@ -98,6 +146,22 @@ def decrypt_string(self, content: str, key: int = 0) -> str: output: decrypted string 'content' if key not passed the method uses the key by the constructor. otherwise key = 1 + + Empty list + >>> XORCipher().decrypt_string("", 5) + '' + + One key + >>> XORCipher().decrypt_string("hallo welt", 1) + 'i`mmn!vdmu' + + Normal key + >>> XORCipher().decrypt_string("HALLO WELT", 32) + 'hallo\\x00welt' + + Key greater than 255 + >>> XORCipher().decrypt_string("hallo welt", 256) + 'hallo welt' """ # precondition @@ -172,6 +236,11 @@ def decrypt_file(self, file: str, key: int) -> bool: return True +if __name__ == "__main__": + from doctest import testmod + + testmod() + # Tests # crypt = XORCipher() # key = 67