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:
Dhruv Manilawala 2021-04-04 10:52:12 +05:30 committed by GitHub
parent 806b3864c3
commit 60895366c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 207 additions and 210 deletions

View File

@ -23,7 +23,7 @@ jobs:
python -m pip install mypy pytest-cov -r requirements.txt
# FIXME: #4052 fix mypy errors in the exclude directories and remove them below
- 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
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
- if: ${{ success() }}

View File

@ -241,9 +241,7 @@ class DiffieHellman:
return sha256(str(shared_key).encode()).hexdigest()
@staticmethod
def is_valid_public_key_static(
local_private_key_str: str, remote_public_key_str: str, prime: int
) -> bool:
def is_valid_public_key_static(remote_public_key_str: int, prime: int) -> bool:
# 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 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)
remote_public_key = int(remote_public_key_str, base=16)
prime = primes[group]["prime"]
if not DiffieHellman.is_valid_public_key_static(
local_private_key, remote_public_key, prime
):
if not DiffieHellman.is_valid_public_key_static(remote_public_key, prime):
raise ValueError("Invalid public key")
shared_key = pow(remote_public_key, local_private_key, prime)
return sha256(str(shared_key).encode()).hexdigest()

View File

@ -64,13 +64,12 @@ class HillCipher:
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
"""
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.decrypt_key = None
self.break_key = encrypt_key.shape[0]
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):
batch = text[i : i + self.break_key]
batch_vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([batch_vec]).T
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
0
]
@ -151,7 +150,7 @@ class HillCipher:
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.make_decrypt_key()
@ -184,17 +183,15 @@ class HillCipher:
>>> hill_cipher.decrypt('85FF00')
'HELLOO'
"""
self.decrypt_key = self.make_decrypt_key()
decrypt_key = self.make_decrypt_key()
text = self.process_text(text.upper())
decrypted = ""
for i in range(0, len(text) - self.break_key + 1, self.break_key):
batch = text[i : i + self.break_key]
batch_vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([batch_vec]).T
batch_decrypted = self.modulus(self.decrypt_key.dot(batch_vec)).T.tolist()[
0
]
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_decrypted = self.modulus(decrypt_key.dot(batch_vec)).T.tolist()[0]
decrypted_batch = "".join(
self.replace_digits(num) for num in batch_decrypted
)
@ -203,12 +200,12 @@ class HillCipher:
return decrypted
def main():
def main() -> None:
N = int(input("Enter the order of the encryption key: "))
hill_matrix = []
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()]
hill_matrix.append(row)

View File

@ -29,8 +29,8 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
# print(temp)
alpha = []
modalpha = []
for i in range(65, 91):
t = chr(i)
for j in range(65, 91):
t = chr(j)
alpha.append(t)
if t not in temp:
temp.append(t)
@ -38,23 +38,23 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
r = int(26 / 4)
# print(r)
k = 0
for i in range(r):
t = []
for _ in range(r):
s = []
for j in range(len_temp):
t.append(temp[k])
s.append(temp[k])
if not (k < 25):
break
k += 1
modalpha.append(t)
modalpha.append(s)
# print(modalpha)
d = {}
j = 0
k = 0
for j in range(len_temp):
for i in modalpha:
if not (len(i) - 1 >= j):
for m in modalpha:
if not (len(m) - 1 >= j):
break
d[alpha[k]] = i[j]
d[alpha[k]] = m[j]
if not k < 25:
break
k += 1

View File

@ -1,7 +1,11 @@
from typing import Literal
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")
'Pcssi Bidsm'
@ -40,7 +44,7 @@ def decrypt_message(key: str, message: str) -> str:
return translate_message(key, message, "decrypt")
def main():
def main() -> None:
message = "Hello World"
key = "QWERTYUIOPASDFGHJKLZXCVBNM"
mode = "decrypt" # set to 'encrypt' or 'decrypt'

View File

@ -83,7 +83,7 @@ def decrypt(message: str) -> str:
return decipher
def main():
def main() -> None:
message = "Morse code here"
result = encrypt(message.upper())
print(result)

View File

@ -2,7 +2,8 @@ import random
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"""
plain = [ord(i) for i in text]
key = []
@ -14,14 +15,14 @@ class Onepad:
key.append(k)
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."""
plain = []
for i in range(len(key)):
p = int((cipher[i] - (key[i]) ** 2) / key[i])
plain.append(chr(p))
plain = "".join([i for i in plain])
return plain
return "".join([i for i in plain])
if __name__ == "__main__":

View File

@ -1,8 +1,9 @@
import itertools
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)
while True:
chunk = tuple(itertools.islice(it, size))
@ -37,7 +38,7 @@ def prepare_input(dirty: str) -> str:
return clean
def generate_table(key: str) -> [str]:
def generate_table(key: str) -> list[str]:
# I and J are used interchangeably to allow
# us to use a 5x5 table (25 letters)

View File

@ -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
[('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
@ -60,30 +60,21 @@ def decrypt(key: str, words: str) -> str:
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 = [
... ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
... ('ABCDEFGHIJKLM', 'STUVWXYZNOPQR'), ('ABCDEFGHIJKLM', 'QRSTUVWXYZNOP'),
... ('ABCDEFGHIJKLM', 'WXYZNOPQRSTUV'), ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST')]
>>> get_position(table, 'A')
(None, None)
>>> get_position(generate_table('marvin')[0], 'M')
(0, 12)
"""
if char in table[0]:
row = 0
else:
row = 1 if char in table[1] else -1
return (None, None) if row == -1 else (row, table[row].index(char))
# `char` is either in the 0th row or the 1st row
row = 0 if char in table[0] else 1
col = table[row].index(char)
return row, col
def get_opponent(table: [(str, str)], char: str) -> str:
def get_opponent(table: tuple[str, str], char: str) -> str:
"""
>>> table = [
... ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST'), ('ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ'),
... ('ABCDEFGHIJKLM', 'STUVWXYZNOPQR'), ('ABCDEFGHIJKLM', 'QRSTUVWXYZNOP'),
... ('ABCDEFGHIJKLM', 'WXYZNOPQRSTUV'), ('ABCDEFGHIJKLM', 'UVWXYZNOPQRST')]
>>> get_opponent(table, 'A')
'A'
>>> get_opponent(generate_table('marvin')[0], 'M')
'T'
"""
row, col = get_position(table, char.upper())
if row == 1:
@ -97,14 +88,16 @@ if __name__ == "__main__":
doctest.testmod() # Fist ensure that all our tests are passing...
"""
ENTER KEY: marvin
ENTER TEXT TO ENCRYPT: jessica
ENCRYPTED: QRACRWU
DECRYPTED WITH KEY: JESSICA
Demo:
Enter key: marvin
Enter text to encrypt: jessica
Encrypted: QRACRWU
Decrypted with key: JESSICA
"""
key = input("ENTER KEY: ").strip()
text = input("ENTER TEXT TO ENCRYPT: ").strip()
key = input("Enter key: ").strip()
text = input("Enter text to encrypt: ").strip()
cipher_text = encrypt(key, text)
print(f"ENCRYPTED: {cipher_text}")
print(f"DECRYPTED WITH KEY: {decrypt(key, cipher_text)}")
print(f"Encrypted: {cipher_text}")
print(f"Decrypted with key: {decrypt(key, cipher_text)}")

View File

@ -20,7 +20,7 @@ def encrypt(input_string: str, key: int) -> str:
...
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
if key <= 0:
@ -31,8 +31,8 @@ def encrypt(input_string: str, key: int) -> str:
for position, character in enumerate(input_string):
num = position % (lowest * 2) # puts it in bounds
num = min(num, lowest * 2 - num) # creates zigzag pattern
grid[num].append(character)
grid = ["".join(row) for row in grid]
temp_grid[num].append(character)
grid = ["".join(row) for row in temp_grid]
output_string = "".join(grid)
return output_string
@ -63,7 +63,7 @@ def decrypt(input_string: str, key: int) -> str:
if key == 1:
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)):
num = position % (lowest * 2) # puts it in bounds
num = min(num, lowest * 2 - num) # creates zigzag pattern
@ -84,7 +84,7 @@ def decrypt(input_string: str, key: int) -> str:
return output_string
def bruteforce(input_string: str) -> dict:
def bruteforce(input_string: str) -> dict[int, str]:
"""Uses decrypt function by guessing every key
>>> bruteforce("HWe olordll")[4]

View File

@ -20,7 +20,7 @@ def dencrypt(s: str, n: int = 13) -> str:
return out
def main():
def main() -> None:
s0 = input("Enter message: ")
s1 = dencrypt(s0, 13)

View File

@ -7,7 +7,114 @@ DEFAULT_BLOCK_SIZE = 128
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"
response = input(r"Encrypt\Decrypt [e\d]: ")
@ -21,130 +128,23 @@ def main():
rkg.makeKeyFiles("rsa", 1024)
message = input("\nEnter message: ")
pubKeyFilename = "rsa_pubkey.txt"
pubkey_filename = "rsa_pubkey.txt"
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(encryptedText)
elif mode == "decrypt":
privKeyFilename = "rsa_privkey.txt"
privkey_filename = "rsa_privkey.txt"
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...")
with open("rsa_decryption.txt", "w") as dec:
dec.write(decryptedText)
dec.write(decrypted_text)
print("\nDecryption:")
print(decryptedText)
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)
print(decrypted_text)
if __name__ == "__main__":

View File

@ -13,7 +13,7 @@ import math
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
Return: [p, q]

View File

@ -1,5 +1,6 @@
import random
import string
from typing import Optional
class ShuffledShiftCipher:
@ -26,7 +27,7 @@ class 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
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.__shift_key = self.__make_shift_key()
def __str__(self):
def __str__(self) -> str:
"""
:return: passcode of the cipher object
"""
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
@ -54,7 +55,7 @@ class ShuffledShiftCipher:
iterlist[i] *= -1
return iterlist
def __passcode_creator(self) -> list:
def __passcode_creator(self) -> list[str]:
"""
Creates a random password from the selection buffer of
1. uppercase letters of the English alphabet
@ -65,10 +66,10 @@ class ShuffledShiftCipher:
:return: a password of a random length between 10 to 20
"""
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
def __make_key_list(self) -> list:
def __make_key_list(self) -> list[str]:
"""
Shuffles the ordered character choices by pivoting at breakpoints
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
# points and pivot each substring
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
for i in key_list_options:
@ -109,7 +110,7 @@ class ShuffledShiftCipher:
# keys_l
if i in breakpoints or i == key_list_options[-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
return keys_l
@ -167,7 +168,7 @@ class ShuffledShiftCipher:
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()
'Hello, this is a modified Caesar cipher'

View File

@ -15,7 +15,7 @@ def remove_duplicates(key: str) -> str:
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.
:param key: keyword to use
@ -40,7 +40,7 @@ def create_cipher_map(key: str) -> dict:
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.
: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())
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
: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())
def main():
def main() -> None:
"""
Handles I/O
:return: void

View File

@ -4,7 +4,7 @@ import sys
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def main():
def main() -> None:
message = input("Enter message: ")
key = "LFWOAYUISVKMNXPBDCRJTQEGHZ"
resp = input("Encrypt/Decrypt [e/d]: ")
@ -68,7 +68,7 @@ def translateMessage(key: str, message: str, mode: str) -> str:
return translated
def getRandomKey():
def getRandomKey() -> str:
key = list(LETTERS)
random.shuffle(key)
return "".join(key)

View File

@ -1,7 +1,7 @@
# 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 = "", "", ""
tmp = []
@ -16,7 +16,9 @@ def __encryptPart(messagePart: str, character2Number: dict) -> str:
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 = "", ""
result = []
@ -32,7 +34,9 @@ def __decryptPart(messagePart: str, character2Number: dict) -> (str, str, str):
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
alphabet = alphabet.replace(" ", "").upper()
message = message.replace(" ", "").upper()

View File

@ -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: ")
key = int(input("Enter key [2-%s]: " % (len(message) - 1)))
mode = input("Encryption/Decryption [e/d]: ")

View File

@ -5,7 +5,7 @@ import time
from . import transposition_cipher as transCipher
def main():
def main() -> None:
inputFile = "Prehistoric Men.txt"
outputFile = "Output.txt"
key = int(input("Enter key: "))

View File

@ -1,7 +1,7 @@
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def main():
def main() -> None:
message = input("Enter message: ")
key = input("Enter key [alphanumeric]: ")
mode = input("Encrypt/Decrypt [e/d]: ")

View File

@ -28,7 +28,7 @@ class XORCipher:
# private field
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
output: encrypted string 'content' as a list of chars
@ -53,7 +53,7 @@ class XORCipher:
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
output: decrypted string 'content' as a list of chars