mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 15:01:08 +00:00
fix(mypy): type annotations for cipher algorithms (#4306)
* fix(mypy): type annotations for cipher algorithms * Update mypy workflow to include cipher directory * fix: mypy errors in hill_cipher.py * fix build errors
This commit is contained in:
parent
806b3864c3
commit
60895366c0
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
python -m pip install mypy pytest-cov -r requirements.txt
|
python -m pip install mypy pytest-cov -r requirements.txt
|
||||||
# FIXME: #4052 fix mypy errors in the exclude directories and remove them below
|
# FIXME: #4052 fix mypy errors in the exclude directories and remove them below
|
||||||
- run: mypy --ignore-missing-imports
|
- run: mypy --ignore-missing-imports
|
||||||
--exclude '(ciphers|conversions|data_structures|digital_image_processing|dynamic_programming|graphs|linear_algebra|maths|matrix|other|project_euler|scripts|searches|strings*)/$' .
|
--exclude '(conversions|data_structures|digital_image_processing|dynamic_programming|graphs|linear_algebra|maths|matrix|other|project_euler|scripts|searches|strings*)/$' .
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
|
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
|
||||||
- if: ${{ success() }}
|
- if: ${{ success() }}
|
||||||
|
|
|
@ -241,9 +241,7 @@ class DiffieHellman:
|
||||||
return sha256(str(shared_key).encode()).hexdigest()
|
return sha256(str(shared_key).encode()).hexdigest()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_valid_public_key_static(
|
def is_valid_public_key_static(remote_public_key_str: int, prime: int) -> bool:
|
||||||
local_private_key_str: str, remote_public_key_str: str, prime: int
|
|
||||||
) -> bool:
|
|
||||||
# check if the other public key is valid based on NIST SP800-56
|
# check if the other public key is valid based on NIST SP800-56
|
||||||
if 2 <= remote_public_key_str and remote_public_key_str <= prime - 2:
|
if 2 <= remote_public_key_str and remote_public_key_str <= prime - 2:
|
||||||
if pow(remote_public_key_str, (prime - 1) // 2, prime) == 1:
|
if pow(remote_public_key_str, (prime - 1) // 2, prime) == 1:
|
||||||
|
@ -257,9 +255,7 @@ class DiffieHellman:
|
||||||
local_private_key = int(local_private_key_str, base=16)
|
local_private_key = int(local_private_key_str, base=16)
|
||||||
remote_public_key = int(remote_public_key_str, base=16)
|
remote_public_key = int(remote_public_key_str, base=16)
|
||||||
prime = primes[group]["prime"]
|
prime = primes[group]["prime"]
|
||||||
if not DiffieHellman.is_valid_public_key_static(
|
if not DiffieHellman.is_valid_public_key_static(remote_public_key, prime):
|
||||||
local_private_key, remote_public_key, prime
|
|
||||||
):
|
|
||||||
raise ValueError("Invalid public key")
|
raise ValueError("Invalid public key")
|
||||||
shared_key = pow(remote_public_key, local_private_key, prime)
|
shared_key = pow(remote_public_key, local_private_key, prime)
|
||||||
return sha256(str(shared_key).encode()).hexdigest()
|
return sha256(str(shared_key).encode()).hexdigest()
|
||||||
|
|
|
@ -64,13 +64,12 @@ class HillCipher:
|
||||||
|
|
||||||
to_int = numpy.vectorize(lambda x: round(x))
|
to_int = numpy.vectorize(lambda x: round(x))
|
||||||
|
|
||||||
def __init__(self, encrypt_key: int):
|
def __init__(self, encrypt_key: numpy.ndarray) -> None:
|
||||||
"""
|
"""
|
||||||
encrypt_key is an NxN numpy array
|
encrypt_key is an NxN numpy array
|
||||||
"""
|
"""
|
||||||
self.encrypt_key = self.modulus(encrypt_key) # mod36 calc's on the encrypt key
|
self.encrypt_key = self.modulus(encrypt_key) # mod36 calc's on the encrypt key
|
||||||
self.check_determinant() # validate the determinant of the encryption key
|
self.check_determinant() # validate the determinant of the encryption key
|
||||||
self.decrypt_key = None
|
|
||||||
self.break_key = encrypt_key.shape[0]
|
self.break_key = encrypt_key.shape[0]
|
||||||
|
|
||||||
def replace_letters(self, letter: str) -> int:
|
def replace_letters(self, letter: str) -> int:
|
||||||
|
@ -139,8 +138,8 @@ class HillCipher:
|
||||||
|
|
||||||
for i in range(0, len(text) - self.break_key + 1, self.break_key):
|
for i in range(0, len(text) - self.break_key + 1, self.break_key):
|
||||||
batch = text[i : i + self.break_key]
|
batch = text[i : i + self.break_key]
|
||||||
batch_vec = [self.replace_letters(char) for char in batch]
|
vec = [self.replace_letters(char) for char in batch]
|
||||||
batch_vec = numpy.array([batch_vec]).T
|
batch_vec = numpy.array([vec]).T
|
||||||
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
|
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
|
@ -151,7 +150,7 @@ class HillCipher:
|
||||||
|
|
||||||
return encrypted
|
return encrypted
|
||||||
|
|
||||||
def make_decrypt_key(self):
|
def make_decrypt_key(self) -> numpy.ndarray:
|
||||||
"""
|
"""
|
||||||
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
|
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
|
||||||
>>> hill_cipher.make_decrypt_key()
|
>>> hill_cipher.make_decrypt_key()
|
||||||
|
@ -184,17 +183,15 @@ class HillCipher:
|
||||||
>>> hill_cipher.decrypt('85FF00')
|
>>> hill_cipher.decrypt('85FF00')
|
||||||
'HELLOO'
|
'HELLOO'
|
||||||
"""
|
"""
|
||||||
self.decrypt_key = self.make_decrypt_key()
|
decrypt_key = self.make_decrypt_key()
|
||||||
text = self.process_text(text.upper())
|
text = self.process_text(text.upper())
|
||||||
decrypted = ""
|
decrypted = ""
|
||||||
|
|
||||||
for i in range(0, len(text) - self.break_key + 1, self.break_key):
|
for i in range(0, len(text) - self.break_key + 1, self.break_key):
|
||||||
batch = text[i : i + self.break_key]
|
batch = text[i : i + self.break_key]
|
||||||
batch_vec = [self.replace_letters(char) for char in batch]
|
vec = [self.replace_letters(char) for char in batch]
|
||||||
batch_vec = numpy.array([batch_vec]).T
|
batch_vec = numpy.array([vec]).T
|
||||||
batch_decrypted = self.modulus(self.decrypt_key.dot(batch_vec)).T.tolist()[
|
batch_decrypted = self.modulus(decrypt_key.dot(batch_vec)).T.tolist()[0]
|
||||||
0
|
|
||||||
]
|
|
||||||
decrypted_batch = "".join(
|
decrypted_batch = "".join(
|
||||||
self.replace_digits(num) for num in batch_decrypted
|
self.replace_digits(num) for num in batch_decrypted
|
||||||
)
|
)
|
||||||
|
@ -203,12 +200,12 @@ class HillCipher:
|
||||||
return decrypted
|
return decrypted
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
N = int(input("Enter the order of the encryption key: "))
|
N = int(input("Enter the order of the encryption key: "))
|
||||||
hill_matrix = []
|
hill_matrix = []
|
||||||
|
|
||||||
print("Enter each row of the encryption key with space separated integers")
|
print("Enter each row of the encryption key with space separated integers")
|
||||||
for i in range(N):
|
for _ in range(N):
|
||||||
row = [int(x) for x in input().split()]
|
row = [int(x) for x in input().split()]
|
||||||
hill_matrix.append(row)
|
hill_matrix.append(row)
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
|
||||||
# print(temp)
|
# print(temp)
|
||||||
alpha = []
|
alpha = []
|
||||||
modalpha = []
|
modalpha = []
|
||||||
for i in range(65, 91):
|
for j in range(65, 91):
|
||||||
t = chr(i)
|
t = chr(j)
|
||||||
alpha.append(t)
|
alpha.append(t)
|
||||||
if t not in temp:
|
if t not in temp:
|
||||||
temp.append(t)
|
temp.append(t)
|
||||||
|
@ -38,23 +38,23 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
|
||||||
r = int(26 / 4)
|
r = int(26 / 4)
|
||||||
# print(r)
|
# print(r)
|
||||||
k = 0
|
k = 0
|
||||||
for i in range(r):
|
for _ in range(r):
|
||||||
t = []
|
s = []
|
||||||
for j in range(len_temp):
|
for j in range(len_temp):
|
||||||
t.append(temp[k])
|
s.append(temp[k])
|
||||||
if not (k < 25):
|
if not (k < 25):
|
||||||
break
|
break
|
||||||
k += 1
|
k += 1
|
||||||
modalpha.append(t)
|
modalpha.append(s)
|
||||||
# print(modalpha)
|
# print(modalpha)
|
||||||
d = {}
|
d = {}
|
||||||
j = 0
|
j = 0
|
||||||
k = 0
|
k = 0
|
||||||
for j in range(len_temp):
|
for j in range(len_temp):
|
||||||
for i in modalpha:
|
for m in modalpha:
|
||||||
if not (len(i) - 1 >= j):
|
if not (len(m) - 1 >= j):
|
||||||
break
|
break
|
||||||
d[alpha[k]] = i[j]
|
d[alpha[k]] = m[j]
|
||||||
if not k < 25:
|
if not k < 25:
|
||||||
break
|
break
|
||||||
k += 1
|
k += 1
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
|
||||||
def translate_message(key, message, mode):
|
def translate_message(
|
||||||
|
key: str, message: str, mode: Literal["encrypt", "decrypt"]
|
||||||
|
) -> str:
|
||||||
"""
|
"""
|
||||||
>>> translate_message("QWERTYUIOPASDFGHJKLZXCVBNM","Hello World","encrypt")
|
>>> translate_message("QWERTYUIOPASDFGHJKLZXCVBNM","Hello World","encrypt")
|
||||||
'Pcssi Bidsm'
|
'Pcssi Bidsm'
|
||||||
|
@ -40,7 +44,7 @@ def decrypt_message(key: str, message: str) -> str:
|
||||||
return translate_message(key, message, "decrypt")
|
return translate_message(key, message, "decrypt")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
message = "Hello World"
|
message = "Hello World"
|
||||||
key = "QWERTYUIOPASDFGHJKLZXCVBNM"
|
key = "QWERTYUIOPASDFGHJKLZXCVBNM"
|
||||||
mode = "decrypt" # set to 'encrypt' or 'decrypt'
|
mode = "decrypt" # set to 'encrypt' or 'decrypt'
|
||||||
|
|
|
@ -83,7 +83,7 @@ def decrypt(message: str) -> str:
|
||||||
return decipher
|
return decipher
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
message = "Morse code here"
|
message = "Morse code here"
|
||||||
result = encrypt(message.upper())
|
result = encrypt(message.upper())
|
||||||
print(result)
|
print(result)
|
||||||
|
|
|
@ -2,7 +2,8 @@ import random
|
||||||
|
|
||||||
|
|
||||||
class Onepad:
|
class Onepad:
|
||||||
def encrypt(self, text: str) -> ([str], [int]):
|
@staticmethod
|
||||||
|
def encrypt(text: str) -> tuple[list[int], list[int]]:
|
||||||
"""Function to encrypt text using pseudo-random numbers"""
|
"""Function to encrypt text using pseudo-random numbers"""
|
||||||
plain = [ord(i) for i in text]
|
plain = [ord(i) for i in text]
|
||||||
key = []
|
key = []
|
||||||
|
@ -14,14 +15,14 @@ class Onepad:
|
||||||
key.append(k)
|
key.append(k)
|
||||||
return cipher, key
|
return cipher, key
|
||||||
|
|
||||||
def decrypt(self, cipher: [str], key: [int]) -> str:
|
@staticmethod
|
||||||
|
def decrypt(cipher: list[int], key: list[int]) -> str:
|
||||||
"""Function to decrypt text using pseudo-random numbers."""
|
"""Function to decrypt text using pseudo-random numbers."""
|
||||||
plain = []
|
plain = []
|
||||||
for i in range(len(key)):
|
for i in range(len(key)):
|
||||||
p = int((cipher[i] - (key[i]) ** 2) / key[i])
|
p = int((cipher[i] - (key[i]) ** 2) / key[i])
|
||||||
plain.append(chr(p))
|
plain.append(chr(p))
|
||||||
plain = "".join([i for i in plain])
|
return "".join([i for i in plain])
|
||||||
return plain
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import itertools
|
import itertools
|
||||||
import string
|
import string
|
||||||
|
from typing import Generator, Iterable
|
||||||
|
|
||||||
|
|
||||||
def chunker(seq, size):
|
def chunker(seq: Iterable[str], size: int) -> Generator[tuple[str, ...], None, None]:
|
||||||
it = iter(seq)
|
it = iter(seq)
|
||||||
while True:
|
while True:
|
||||||
chunk = tuple(itertools.islice(it, size))
|
chunk = tuple(itertools.islice(it, size))
|
||||||
|
@ -37,7 +38,7 @@ def prepare_input(dirty: str) -> str:
|
||||||
return clean
|
return clean
|
||||||
|
|
||||||
|
|
||||||
def generate_table(key: str) -> [str]:
|
def generate_table(key: str) -> list[str]:
|
||||||
|
|
||||||
# I and J are used interchangeably to allow
|
# I and J are used interchangeably to allow
|
||||||
# us to use a 5x5 table (25 letters)
|
# us to use a 5x5 table (25 letters)
|
||||||
|
|
|
@ -28,7 +28,7 @@ alphabet = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def generate_table(key: str) -> [(str, str)]:
|
def generate_table(key: str) -> list[tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
>>> generate_table('marvin') # doctest: +NORMALIZE_WHITESPACE
|
>>> generate_table('marvin') # doctest: +NORMALIZE_WHITESPACE
|
||||||
[('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
|
[('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
|
||||||
|
@ -60,30 +60,21 @@ def decrypt(key: str, words: str) -> str:
|
||||||
return encrypt(key, words)
|
return encrypt(key, words)
|
||||||
|
|
||||||
|
|
||||||
def get_position(table: [(str, str)], char: str) -> (int, int) or (None, None):
|
def get_position(table: tuple[str, str], char: str) -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
>>> table = [
|
>>> get_position(generate_table('marvin')[0], 'M')
|
||||||
... ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
|
(0, 12)
|
||||||
... ('ABCDEFGHIJKLM', 'STUVWXYZNOPQR'), ('ABCDEFGHIJKLM', 'QRSTUVWXYZNOP'),
|
|
||||||
... ('ABCDEFGHIJKLM', 'WXYZNOPQRSTUV'), ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST')]
|
|
||||||
>>> get_position(table, 'A')
|
|
||||||
(None, None)
|
|
||||||
"""
|
"""
|
||||||
if char in table[0]:
|
# `char` is either in the 0th row or the 1st row
|
||||||
row = 0
|
row = 0 if char in table[0] else 1
|
||||||
else:
|
col = table[row].index(char)
|
||||||
row = 1 if char in table[1] else -1
|
return row, col
|
||||||
return (None, None) if row == -1 else (row, table[row].index(char))
|
|
||||||
|
|
||||||
|
|
||||||
def get_opponent(table: [(str, str)], char: str) -> str:
|
def get_opponent(table: tuple[str, str], char: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> table = [
|
>>> get_opponent(generate_table('marvin')[0], 'M')
|
||||||
... ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
|
'T'
|
||||||
... ('ABCDEFGHIJKLM', 'STUVWXYZNOPQR'), ('ABCDEFGHIJKLM', 'QRSTUVWXYZNOP'),
|
|
||||||
... ('ABCDEFGHIJKLM', 'WXYZNOPQRSTUV'), ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST')]
|
|
||||||
>>> get_opponent(table, 'A')
|
|
||||||
'A'
|
|
||||||
"""
|
"""
|
||||||
row, col = get_position(table, char.upper())
|
row, col = get_position(table, char.upper())
|
||||||
if row == 1:
|
if row == 1:
|
||||||
|
@ -97,14 +88,16 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
doctest.testmod() # Fist ensure that all our tests are passing...
|
doctest.testmod() # Fist ensure that all our tests are passing...
|
||||||
"""
|
"""
|
||||||
ENTER KEY: marvin
|
Demo:
|
||||||
ENTER TEXT TO ENCRYPT: jessica
|
|
||||||
ENCRYPTED: QRACRWU
|
Enter key: marvin
|
||||||
DECRYPTED WITH KEY: JESSICA
|
Enter text to encrypt: jessica
|
||||||
|
Encrypted: QRACRWU
|
||||||
|
Decrypted with key: JESSICA
|
||||||
"""
|
"""
|
||||||
key = input("ENTER KEY: ").strip()
|
key = input("Enter key: ").strip()
|
||||||
text = input("ENTER TEXT TO ENCRYPT: ").strip()
|
text = input("Enter text to encrypt: ").strip()
|
||||||
cipher_text = encrypt(key, text)
|
cipher_text = encrypt(key, text)
|
||||||
|
|
||||||
print(f"ENCRYPTED: {cipher_text}")
|
print(f"Encrypted: {cipher_text}")
|
||||||
print(f"DECRYPTED WITH KEY: {decrypt(key, cipher_text)}")
|
print(f"Decrypted with key: {decrypt(key, cipher_text)}")
|
||||||
|
|
|
@ -20,7 +20,7 @@ def encrypt(input_string: str, key: int) -> str:
|
||||||
...
|
...
|
||||||
TypeError: sequence item 0: expected str instance, int found
|
TypeError: sequence item 0: expected str instance, int found
|
||||||
"""
|
"""
|
||||||
grid = [[] for _ in range(key)]
|
temp_grid: list[list[str]] = [[] for _ in range(key)]
|
||||||
lowest = key - 1
|
lowest = key - 1
|
||||||
|
|
||||||
if key <= 0:
|
if key <= 0:
|
||||||
|
@ -31,8 +31,8 @@ def encrypt(input_string: str, key: int) -> str:
|
||||||
for position, character in enumerate(input_string):
|
for position, character in enumerate(input_string):
|
||||||
num = position % (lowest * 2) # puts it in bounds
|
num = position % (lowest * 2) # puts it in bounds
|
||||||
num = min(num, lowest * 2 - num) # creates zigzag pattern
|
num = min(num, lowest * 2 - num) # creates zigzag pattern
|
||||||
grid[num].append(character)
|
temp_grid[num].append(character)
|
||||||
grid = ["".join(row) for row in grid]
|
grid = ["".join(row) for row in temp_grid]
|
||||||
output_string = "".join(grid)
|
output_string = "".join(grid)
|
||||||
|
|
||||||
return output_string
|
return output_string
|
||||||
|
@ -63,7 +63,7 @@ def decrypt(input_string: str, key: int) -> str:
|
||||||
if key == 1:
|
if key == 1:
|
||||||
return input_string
|
return input_string
|
||||||
|
|
||||||
temp_grid = [[] for _ in range(key)] # generates template
|
temp_grid: list[list[str]] = [[] for _ in range(key)] # generates template
|
||||||
for position in range(len(input_string)):
|
for position in range(len(input_string)):
|
||||||
num = position % (lowest * 2) # puts it in bounds
|
num = position % (lowest * 2) # puts it in bounds
|
||||||
num = min(num, lowest * 2 - num) # creates zigzag pattern
|
num = min(num, lowest * 2 - num) # creates zigzag pattern
|
||||||
|
@ -84,7 +84,7 @@ def decrypt(input_string: str, key: int) -> str:
|
||||||
return output_string
|
return output_string
|
||||||
|
|
||||||
|
|
||||||
def bruteforce(input_string: str) -> dict:
|
def bruteforce(input_string: str) -> dict[int, str]:
|
||||||
"""Uses decrypt function by guessing every key
|
"""Uses decrypt function by guessing every key
|
||||||
|
|
||||||
>>> bruteforce("HWe olordll")[4]
|
>>> bruteforce("HWe olordll")[4]
|
||||||
|
|
|
@ -20,7 +20,7 @@ def dencrypt(s: str, n: int = 13) -> str:
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
s0 = input("Enter message: ")
|
s0 = input("Enter message: ")
|
||||||
|
|
||||||
s1 = dencrypt(s0, 13)
|
s1 = dencrypt(s0, 13)
|
||||||
|
|
|
@ -7,7 +7,114 @@ DEFAULT_BLOCK_SIZE = 128
|
||||||
BYTE_SIZE = 256
|
BYTE_SIZE = 256
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def get_blocks_from_text(
|
||||||
|
message: str, block_size: int = DEFAULT_BLOCK_SIZE
|
||||||
|
) -> list[int]:
|
||||||
|
message_bytes = message.encode("ascii")
|
||||||
|
|
||||||
|
block_ints = []
|
||||||
|
for block_start in range(0, len(message_bytes), block_size):
|
||||||
|
block_int = 0
|
||||||
|
for i in range(block_start, min(block_start + block_size, len(message_bytes))):
|
||||||
|
block_int += message_bytes[i] * (BYTE_SIZE ** (i % block_size))
|
||||||
|
block_ints.append(block_int)
|
||||||
|
return block_ints
|
||||||
|
|
||||||
|
|
||||||
|
def get_text_from_blocks(
|
||||||
|
block_ints: list[int], message_length: int, block_size: int = DEFAULT_BLOCK_SIZE
|
||||||
|
) -> str:
|
||||||
|
message: list[str] = []
|
||||||
|
for block_int in block_ints:
|
||||||
|
block_message: list[str] = []
|
||||||
|
for i in range(block_size - 1, -1, -1):
|
||||||
|
if len(message) + i < message_length:
|
||||||
|
ascii_number = block_int // (BYTE_SIZE ** i)
|
||||||
|
block_int = block_int % (BYTE_SIZE ** i)
|
||||||
|
block_message.insert(0, chr(ascii_number))
|
||||||
|
message.extend(block_message)
|
||||||
|
return "".join(message)
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_message(
|
||||||
|
message: str, key: tuple[int, int], blockSize: int = DEFAULT_BLOCK_SIZE
|
||||||
|
) -> list[int]:
|
||||||
|
encrypted_blocks = []
|
||||||
|
n, e = key
|
||||||
|
|
||||||
|
for block in get_blocks_from_text(message, blockSize):
|
||||||
|
encrypted_blocks.append(pow(block, e, n))
|
||||||
|
return encrypted_blocks
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt_message(
|
||||||
|
encrypted_blocks: list[int],
|
||||||
|
message_length: int,
|
||||||
|
key: tuple[int, int],
|
||||||
|
block_size: int = DEFAULT_BLOCK_SIZE,
|
||||||
|
) -> str:
|
||||||
|
decrypted_blocks = []
|
||||||
|
n, d = key
|
||||||
|
for block in encrypted_blocks:
|
||||||
|
decrypted_blocks.append(pow(block, d, n))
|
||||||
|
return get_text_from_blocks(decrypted_blocks, message_length, block_size)
|
||||||
|
|
||||||
|
|
||||||
|
def read_key_file(key_filename: str) -> tuple[int, int, int]:
|
||||||
|
with open(key_filename) as fo:
|
||||||
|
content = fo.read()
|
||||||
|
key_size, n, EorD = content.split(",")
|
||||||
|
return (int(key_size), int(n), int(EorD))
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_and_write_to_file(
|
||||||
|
message_filename: str,
|
||||||
|
key_filename: str,
|
||||||
|
message: str,
|
||||||
|
block_size: int = DEFAULT_BLOCK_SIZE,
|
||||||
|
) -> str:
|
||||||
|
key_size, n, e = read_key_file(key_filename)
|
||||||
|
if key_size < block_size * 8:
|
||||||
|
sys.exit(
|
||||||
|
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
||||||
|
"requires the block size to be equal to or greater than the key size. "
|
||||||
|
"Either decrease the block size or use different keys."
|
||||||
|
% (block_size * 8, key_size)
|
||||||
|
)
|
||||||
|
|
||||||
|
encrypted_blocks = [str(i) for i in encrypt_message(message, (n, e), block_size)]
|
||||||
|
|
||||||
|
encrypted_content = ",".join(encrypted_blocks)
|
||||||
|
encrypted_content = f"{len(message)}_{block_size}_{encrypted_content}"
|
||||||
|
with open(message_filename, "w") as fo:
|
||||||
|
fo.write(encrypted_content)
|
||||||
|
return encrypted_content
|
||||||
|
|
||||||
|
|
||||||
|
def read_from_file_and_decrypt(message_filename: str, key_filename: str) -> str:
|
||||||
|
key_size, n, d = read_key_file(key_filename)
|
||||||
|
with open(message_filename) as fo:
|
||||||
|
content = fo.read()
|
||||||
|
message_length_str, block_size_str, encrypted_message = content.split("_")
|
||||||
|
message_length = int(message_length_str)
|
||||||
|
block_size = int(block_size_str)
|
||||||
|
|
||||||
|
if key_size < block_size * 8:
|
||||||
|
sys.exit(
|
||||||
|
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
||||||
|
"requires the block size to be equal to or greater than the key size. "
|
||||||
|
"Did you specify the correct key file and encrypted file?"
|
||||||
|
% (block_size * 8, key_size)
|
||||||
|
)
|
||||||
|
|
||||||
|
encrypted_blocks = []
|
||||||
|
for block in encrypted_message.split(","):
|
||||||
|
encrypted_blocks.append(int(block))
|
||||||
|
|
||||||
|
return decrypt_message(encrypted_blocks, message_length, (n, d), block_size)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
filename = "encrypted_file.txt"
|
filename = "encrypted_file.txt"
|
||||||
response = input(r"Encrypt\Decrypt [e\d]: ")
|
response = input(r"Encrypt\Decrypt [e\d]: ")
|
||||||
|
|
||||||
|
@ -21,130 +128,23 @@ def main():
|
||||||
rkg.makeKeyFiles("rsa", 1024)
|
rkg.makeKeyFiles("rsa", 1024)
|
||||||
|
|
||||||
message = input("\nEnter message: ")
|
message = input("\nEnter message: ")
|
||||||
pubKeyFilename = "rsa_pubkey.txt"
|
pubkey_filename = "rsa_pubkey.txt"
|
||||||
print("Encrypting and writing to %s..." % (filename))
|
print("Encrypting and writing to %s..." % (filename))
|
||||||
encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message)
|
encryptedText = encrypt_and_write_to_file(filename, pubkey_filename, message)
|
||||||
|
|
||||||
print("\nEncrypted text:")
|
print("\nEncrypted text:")
|
||||||
print(encryptedText)
|
print(encryptedText)
|
||||||
|
|
||||||
elif mode == "decrypt":
|
elif mode == "decrypt":
|
||||||
privKeyFilename = "rsa_privkey.txt"
|
privkey_filename = "rsa_privkey.txt"
|
||||||
print("Reading from %s and decrypting..." % (filename))
|
print("Reading from %s and decrypting..." % (filename))
|
||||||
decryptedText = readFromFileAndDecrypt(filename, privKeyFilename)
|
decrypted_text = read_from_file_and_decrypt(filename, privkey_filename)
|
||||||
print("writing decryption to rsa_decryption.txt...")
|
print("writing decryption to rsa_decryption.txt...")
|
||||||
with open("rsa_decryption.txt", "w") as dec:
|
with open("rsa_decryption.txt", "w") as dec:
|
||||||
dec.write(decryptedText)
|
dec.write(decrypted_text)
|
||||||
|
|
||||||
print("\nDecryption:")
|
print("\nDecryption:")
|
||||||
print(decryptedText)
|
print(decrypted_text)
|
||||||
|
|
||||||
|
|
||||||
def getBlocksFromText(message: int, blockSize: int = DEFAULT_BLOCK_SIZE) -> [int]:
|
|
||||||
messageBytes = message.encode("ascii")
|
|
||||||
|
|
||||||
blockInts = []
|
|
||||||
for blockStart in range(0, len(messageBytes), blockSize):
|
|
||||||
blockInt = 0
|
|
||||||
for i in range(blockStart, min(blockStart + blockSize, len(messageBytes))):
|
|
||||||
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
|
|
||||||
blockInts.append(blockInt)
|
|
||||||
return blockInts
|
|
||||||
|
|
||||||
|
|
||||||
def getTextFromBlocks(
|
|
||||||
blockInts: [int], messageLength: int, blockSize: int = DEFAULT_BLOCK_SIZE
|
|
||||||
) -> str:
|
|
||||||
message = []
|
|
||||||
for blockInt in blockInts:
|
|
||||||
blockMessage = []
|
|
||||||
for i in range(blockSize - 1, -1, -1):
|
|
||||||
if len(message) + i < messageLength:
|
|
||||||
asciiNumber = blockInt // (BYTE_SIZE ** i)
|
|
||||||
blockInt = blockInt % (BYTE_SIZE ** i)
|
|
||||||
blockMessage.insert(0, chr(asciiNumber))
|
|
||||||
message.extend(blockMessage)
|
|
||||||
return "".join(message)
|
|
||||||
|
|
||||||
|
|
||||||
def encryptMessage(
|
|
||||||
message: str, key: (int, int), blockSize: int = DEFAULT_BLOCK_SIZE
|
|
||||||
) -> [int]:
|
|
||||||
encryptedBlocks = []
|
|
||||||
n, e = key
|
|
||||||
|
|
||||||
for block in getBlocksFromText(message, blockSize):
|
|
||||||
encryptedBlocks.append(pow(block, e, n))
|
|
||||||
return encryptedBlocks
|
|
||||||
|
|
||||||
|
|
||||||
def decryptMessage(
|
|
||||||
encryptedBlocks: [int],
|
|
||||||
messageLength: int,
|
|
||||||
key: (int, int),
|
|
||||||
blockSize: int = DEFAULT_BLOCK_SIZE,
|
|
||||||
) -> str:
|
|
||||||
decryptedBlocks = []
|
|
||||||
n, d = key
|
|
||||||
for block in encryptedBlocks:
|
|
||||||
decryptedBlocks.append(pow(block, d, n))
|
|
||||||
return getTextFromBlocks(decryptedBlocks, messageLength, blockSize)
|
|
||||||
|
|
||||||
|
|
||||||
def readKeyFile(keyFilename: str) -> (int, int, int):
|
|
||||||
with open(keyFilename) as fo:
|
|
||||||
content = fo.read()
|
|
||||||
keySize, n, EorD = content.split(",")
|
|
||||||
return (int(keySize), int(n), int(EorD))
|
|
||||||
|
|
||||||
|
|
||||||
def encryptAndWriteToFile(
|
|
||||||
messageFilename: str,
|
|
||||||
keyFilename: str,
|
|
||||||
message: str,
|
|
||||||
blockSize: int = DEFAULT_BLOCK_SIZE,
|
|
||||||
) -> str:
|
|
||||||
keySize, n, e = readKeyFile(keyFilename)
|
|
||||||
if keySize < blockSize * 8:
|
|
||||||
sys.exit(
|
|
||||||
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
|
||||||
"requires the block size to be equal to or greater than the key size. "
|
|
||||||
"Either decrease the block size or use different keys."
|
|
||||||
% (blockSize * 8, keySize)
|
|
||||||
)
|
|
||||||
|
|
||||||
encryptedBlocks = encryptMessage(message, (n, e), blockSize)
|
|
||||||
|
|
||||||
for i in range(len(encryptedBlocks)):
|
|
||||||
encryptedBlocks[i] = str(encryptedBlocks[i])
|
|
||||||
encryptedContent = ",".join(encryptedBlocks)
|
|
||||||
encryptedContent = f"{len(message)}_{blockSize}_{encryptedContent}"
|
|
||||||
with open(messageFilename, "w") as fo:
|
|
||||||
fo.write(encryptedContent)
|
|
||||||
return encryptedContent
|
|
||||||
|
|
||||||
|
|
||||||
def readFromFileAndDecrypt(messageFilename: str, keyFilename: str) -> str:
|
|
||||||
keySize, n, d = readKeyFile(keyFilename)
|
|
||||||
with open(messageFilename) as fo:
|
|
||||||
content = fo.read()
|
|
||||||
messageLength, blockSize, encryptedMessage = content.split("_")
|
|
||||||
messageLength = int(messageLength)
|
|
||||||
blockSize = int(blockSize)
|
|
||||||
|
|
||||||
if keySize < blockSize * 8:
|
|
||||||
sys.exit(
|
|
||||||
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
|
||||||
"requires the block size to be equal to or greater than the key size. "
|
|
||||||
"Did you specify the correct key file and encrypted file?"
|
|
||||||
% (blockSize * 8, keySize)
|
|
||||||
)
|
|
||||||
|
|
||||||
encryptedBlocks = []
|
|
||||||
for block in encryptedMessage.split(","):
|
|
||||||
encryptedBlocks.append(int(block))
|
|
||||||
|
|
||||||
return decryptMessage(encryptedBlocks, messageLength, (n, d), blockSize)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -13,7 +13,7 @@ import math
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
def rsafactor(d: int, e: int, N: int) -> [int]:
|
def rsafactor(d: int, e: int, N: int) -> list[int]:
|
||||||
"""
|
"""
|
||||||
This function returns the factors of N, where p*q=N
|
This function returns the factors of N, where p*q=N
|
||||||
Return: [p, q]
|
Return: [p, q]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class ShuffledShiftCipher:
|
class ShuffledShiftCipher:
|
||||||
|
@ -26,7 +27,7 @@ class ShuffledShiftCipher:
|
||||||
cip2 = ShuffledShiftCipher()
|
cip2 = ShuffledShiftCipher()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, passcode: str = None):
|
def __init__(self, passcode: Optional[str] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Initializes a cipher object with a passcode as it's entity
|
Initializes a cipher object with a passcode as it's entity
|
||||||
Note: No new passcode is generated if user provides a passcode
|
Note: No new passcode is generated if user provides a passcode
|
||||||
|
@ -36,13 +37,13 @@ class ShuffledShiftCipher:
|
||||||
self.__key_list = self.__make_key_list()
|
self.__key_list = self.__make_key_list()
|
||||||
self.__shift_key = self.__make_shift_key()
|
self.__shift_key = self.__make_shift_key()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
"""
|
"""
|
||||||
:return: passcode of the cipher object
|
:return: passcode of the cipher object
|
||||||
"""
|
"""
|
||||||
return "Passcode is: " + "".join(self.__passcode)
|
return "Passcode is: " + "".join(self.__passcode)
|
||||||
|
|
||||||
def __neg_pos(self, iterlist: list) -> list:
|
def __neg_pos(self, iterlist: list[int]) -> list[int]:
|
||||||
"""
|
"""
|
||||||
Mutates the list by changing the sign of each alternate element
|
Mutates the list by changing the sign of each alternate element
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ class ShuffledShiftCipher:
|
||||||
iterlist[i] *= -1
|
iterlist[i] *= -1
|
||||||
return iterlist
|
return iterlist
|
||||||
|
|
||||||
def __passcode_creator(self) -> list:
|
def __passcode_creator(self) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Creates a random password from the selection buffer of
|
Creates a random password from the selection buffer of
|
||||||
1. uppercase letters of the English alphabet
|
1. uppercase letters of the English alphabet
|
||||||
|
@ -65,10 +66,10 @@ class ShuffledShiftCipher:
|
||||||
:return: a password of a random length between 10 to 20
|
:return: a password of a random length between 10 to 20
|
||||||
"""
|
"""
|
||||||
choices = string.ascii_letters + string.digits
|
choices = string.ascii_letters + string.digits
|
||||||
password = [random.choice(choices) for i in range(random.randint(10, 20))]
|
password = [random.choice(choices) for _ in range(random.randint(10, 20))]
|
||||||
return password
|
return password
|
||||||
|
|
||||||
def __make_key_list(self) -> list:
|
def __make_key_list(self) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Shuffles the ordered character choices by pivoting at breakpoints
|
Shuffles the ordered character choices by pivoting at breakpoints
|
||||||
Breakpoints are the set of characters in the passcode
|
Breakpoints are the set of characters in the passcode
|
||||||
|
@ -99,7 +100,7 @@ class ShuffledShiftCipher:
|
||||||
# creates points known as breakpoints to break the key_list_options at those
|
# creates points known as breakpoints to break the key_list_options at those
|
||||||
# points and pivot each substring
|
# points and pivot each substring
|
||||||
breakpoints = sorted(set(self.__passcode))
|
breakpoints = sorted(set(self.__passcode))
|
||||||
temp_list = []
|
temp_list: list[str] = []
|
||||||
|
|
||||||
# algorithm for creating a new shuffled list, keys_l, out of key_list_options
|
# algorithm for creating a new shuffled list, keys_l, out of key_list_options
|
||||||
for i in key_list_options:
|
for i in key_list_options:
|
||||||
|
@ -109,7 +110,7 @@ class ShuffledShiftCipher:
|
||||||
# keys_l
|
# keys_l
|
||||||
if i in breakpoints or i == key_list_options[-1]:
|
if i in breakpoints or i == key_list_options[-1]:
|
||||||
keys_l.extend(temp_list[::-1])
|
keys_l.extend(temp_list[::-1])
|
||||||
temp_list = []
|
temp_list.clear()
|
||||||
|
|
||||||
# returning a shuffled keys_l to prevent brute force guessing of shift key
|
# returning a shuffled keys_l to prevent brute force guessing of shift key
|
||||||
return keys_l
|
return keys_l
|
||||||
|
@ -167,7 +168,7 @@ class ShuffledShiftCipher:
|
||||||
return encoded_message
|
return encoded_message
|
||||||
|
|
||||||
|
|
||||||
def test_end_to_end(msg: str = "Hello, this is a modified Caesar cipher"):
|
def test_end_to_end(msg: str = "Hello, this is a modified Caesar cipher") -> str:
|
||||||
"""
|
"""
|
||||||
>>> test_end_to_end()
|
>>> test_end_to_end()
|
||||||
'Hello, this is a modified Caesar cipher'
|
'Hello, this is a modified Caesar cipher'
|
||||||
|
|
|
@ -15,7 +15,7 @@ def remove_duplicates(key: str) -> str:
|
||||||
return key_no_dups
|
return key_no_dups
|
||||||
|
|
||||||
|
|
||||||
def create_cipher_map(key: str) -> dict:
|
def create_cipher_map(key: str) -> dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Returns a cipher map given a keyword.
|
Returns a cipher map given a keyword.
|
||||||
:param key: keyword to use
|
:param key: keyword to use
|
||||||
|
@ -40,7 +40,7 @@ def create_cipher_map(key: str) -> dict:
|
||||||
return cipher_alphabet
|
return cipher_alphabet
|
||||||
|
|
||||||
|
|
||||||
def encipher(message: str, cipher_map: dict) -> str:
|
def encipher(message: str, cipher_map: dict[str, str]) -> str:
|
||||||
"""
|
"""
|
||||||
Enciphers a message given a cipher map.
|
Enciphers a message given a cipher map.
|
||||||
:param message: Message to encipher
|
:param message: Message to encipher
|
||||||
|
@ -52,7 +52,7 @@ def encipher(message: str, cipher_map: dict) -> str:
|
||||||
return "".join(cipher_map.get(ch, ch) for ch in message.upper())
|
return "".join(cipher_map.get(ch, ch) for ch in message.upper())
|
||||||
|
|
||||||
|
|
||||||
def decipher(message: str, cipher_map: dict) -> str:
|
def decipher(message: str, cipher_map: dict[str, str]) -> str:
|
||||||
"""
|
"""
|
||||||
Deciphers a message given a cipher map
|
Deciphers a message given a cipher map
|
||||||
:param message: Message to decipher
|
:param message: Message to decipher
|
||||||
|
@ -67,7 +67,7 @@ def decipher(message: str, cipher_map: dict) -> str:
|
||||||
return "".join(rev_cipher_map.get(ch, ch) for ch in message.upper())
|
return "".join(rev_cipher_map.get(ch, ch) for ch in message.upper())
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
"""
|
"""
|
||||||
Handles I/O
|
Handles I/O
|
||||||
:return: void
|
:return: void
|
||||||
|
|
|
@ -4,7 +4,7 @@ import sys
|
||||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
message = input("Enter message: ")
|
message = input("Enter message: ")
|
||||||
key = "LFWOAYUISVKMNXPBDCRJTQEGHZ"
|
key = "LFWOAYUISVKMNXPBDCRJTQEGHZ"
|
||||||
resp = input("Encrypt/Decrypt [e/d]: ")
|
resp = input("Encrypt/Decrypt [e/d]: ")
|
||||||
|
@ -68,7 +68,7 @@ def translateMessage(key: str, message: str, mode: str) -> str:
|
||||||
return translated
|
return translated
|
||||||
|
|
||||||
|
|
||||||
def getRandomKey():
|
def getRandomKey() -> str:
|
||||||
key = list(LETTERS)
|
key = list(LETTERS)
|
||||||
random.shuffle(key)
|
random.shuffle(key)
|
||||||
return "".join(key)
|
return "".join(key)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# https://en.wikipedia.org/wiki/Trifid_cipher
|
# https://en.wikipedia.org/wiki/Trifid_cipher
|
||||||
|
|
||||||
|
|
||||||
def __encryptPart(messagePart: str, character2Number: dict) -> str:
|
def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str:
|
||||||
one, two, three = "", "", ""
|
one, two, three = "", "", ""
|
||||||
tmp = []
|
tmp = []
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ def __encryptPart(messagePart: str, character2Number: dict) -> str:
|
||||||
return one + two + three
|
return one + two + three
|
||||||
|
|
||||||
|
|
||||||
def __decryptPart(messagePart: str, character2Number: dict) -> (str, str, str):
|
def __decryptPart(
|
||||||
|
messagePart: str, character2Number: dict[str, str]
|
||||||
|
) -> tuple[str, str, str]:
|
||||||
tmp, thisPart = "", ""
|
tmp, thisPart = "", ""
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
|
@ -32,7 +34,9 @@ def __decryptPart(messagePart: str, character2Number: dict) -> (str, str, str):
|
||||||
return result[0], result[1], result[2]
|
return result[0], result[1], result[2]
|
||||||
|
|
||||||
|
|
||||||
def __prepare(message: str, alphabet: str) -> (str, str, dict, dict):
|
def __prepare(
|
||||||
|
message: str, alphabet: str
|
||||||
|
) -> tuple[str, str, dict[str, str], dict[str, str]]:
|
||||||
# Validate message and alphabet, set to upper and remove spaces
|
# Validate message and alphabet, set to upper and remove spaces
|
||||||
alphabet = alphabet.replace(" ", "").upper()
|
alphabet = alphabet.replace(" ", "").upper()
|
||||||
message = message.replace(" ", "").upper()
|
message = message.replace(" ", "").upper()
|
||||||
|
|
|
@ -8,7 +8,7 @@ text. The type of transposition cipher demonstrated under is the ROUTE cipher.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
message = input("Enter message: ")
|
message = input("Enter message: ")
|
||||||
key = int(input("Enter key [2-%s]: " % (len(message) - 1)))
|
key = int(input("Enter key [2-%s]: " % (len(message) - 1)))
|
||||||
mode = input("Encryption/Decryption [e/d]: ")
|
mode = input("Encryption/Decryption [e/d]: ")
|
||||||
|
|
|
@ -5,7 +5,7 @@ import time
|
||||||
from . import transposition_cipher as transCipher
|
from . import transposition_cipher as transCipher
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
inputFile = "Prehistoric Men.txt"
|
inputFile = "Prehistoric Men.txt"
|
||||||
outputFile = "Output.txt"
|
outputFile = "Output.txt"
|
||||||
key = int(input("Enter key: "))
|
key = int(input("Enter key: "))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
message = input("Enter message: ")
|
message = input("Enter message: ")
|
||||||
key = input("Enter key [alphanumeric]: ")
|
key = input("Enter key [alphanumeric]: ")
|
||||||
mode = input("Encrypt/Decrypt [e/d]: ")
|
mode = input("Encrypt/Decrypt [e/d]: ")
|
||||||
|
|
|
@ -28,7 +28,7 @@ class XORCipher:
|
||||||
# private field
|
# private field
|
||||||
self.__key = key
|
self.__key = key
|
||||||
|
|
||||||
def encrypt(self, content: str, key: int) -> [str]:
|
def encrypt(self, content: str, key: int) -> list[str]:
|
||||||
"""
|
"""
|
||||||
input: 'content' of type string and 'key' of type int
|
input: 'content' of type string and 'key' of type int
|
||||||
output: encrypted string 'content' as a list of chars
|
output: encrypted string 'content' as a list of chars
|
||||||
|
@ -53,7 +53,7 @@ class XORCipher:
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def decrypt(self, content: str, key: int) -> [str]:
|
def decrypt(self, content: str, key: int) -> list[str]:
|
||||||
"""
|
"""
|
||||||
input: 'content' of type list and 'key' of type int
|
input: 'content' of type list and 'key' of type int
|
||||||
output: decrypted string 'content' as a list of chars
|
output: decrypted string 'content' as a list of chars
|
||||||
|
|
Loading…
Reference in New Issue
Block a user