Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XOR Cipher: doctests and bug fixes #10840

Merged
merged 4 commits into from
Oct 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 82 additions & 9 deletions ciphers/xor_cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -44,7 +60,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]

Expand All @@ -54,16 +70,32 @@ 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
assert isinstance(key, int)
assert isinstance(content, list)
assert isinstance(content, 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]

Expand All @@ -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
Expand All @@ -81,9 +129,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 = ""
Expand All @@ -99,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
Expand All @@ -107,9 +170,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 = ""
Expand All @@ -132,6 +194,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
Expand All @@ -156,6 +221,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
Expand All @@ -168,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
Expand Down