Skip to content

Commit 14bcb58

Browse files
dhruvmanilacclauss
andauthored
fix(mypy): Fix annotations for 13 cipher algorithms (#4278)
* Initial fix for mypy errors in some cipher algorithms * fix(mypy): Update type hints * fix(mypy): Update type hints for enigma_machine2.py * Update as per the suggestion Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 99a42f2 commit 14bcb58

13 files changed

+101
-89
lines changed

ciphers/a1z26.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@
77
"""
88

99

10-
def encode(plain: str) -> list:
10+
def encode(plain: str) -> list[int]:
1111
"""
1212
>>> encode("myname")
1313
[13, 25, 14, 1, 13, 5]
1414
"""
1515
return [ord(elem) - 96 for elem in plain]
1616

1717

18-
def decode(encoded: list) -> str:
18+
def decode(encoded: list[int]) -> str:
1919
"""
2020
>>> decode([13, 25, 14, 1, 13, 5])
2121
'myname'
2222
"""
2323
return "".join(chr(elem + 96) for elem in encoded)
2424

2525

26-
def main():
27-
encoded = encode(input("->").strip().lower())
26+
def main() -> None:
27+
encoded = encode(input("-> ").strip().lower())
2828
print("Encoded: ", encoded)
2929
print("Decoded:", decode(encoded))
3030

ciphers/affine_cipher.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,6 @@
99
)
1010

1111

12-
def main():
13-
"""
14-
>>> key = get_random_key()
15-
>>> msg = "This is a test!"
16-
>>> decrypt_message(key, encrypt_message(key, msg)) == msg
17-
True
18-
"""
19-
message = input("Enter message: ").strip()
20-
key = int(input("Enter key [2000 - 9000]: ").strip())
21-
mode = input("Encrypt/Decrypt [E/D]: ").strip().lower()
22-
23-
if mode.startswith("e"):
24-
mode = "encrypt"
25-
translated = encrypt_message(key, message)
26-
elif mode.startswith("d"):
27-
mode = "decrypt"
28-
translated = decrypt_message(key, message)
29-
print(f"\n{mode.title()}ed text: \n{translated}")
30-
31-
3212
def check_keys(keyA: int, keyB: int, mode: str) -> None:
3313
if mode == "encrypt":
3414
if keyA == 1:
@@ -80,7 +60,7 @@ def decrypt_message(key: int, message: str) -> str:
8060
keyA, keyB = divmod(key, len(SYMBOLS))
8161
check_keys(keyA, keyB, "decrypt")
8262
plainText = ""
83-
modInverseOfkeyA = cryptomath.findModInverse(keyA, len(SYMBOLS))
63+
modInverseOfkeyA = cryptomath.find_mod_inverse(keyA, len(SYMBOLS))
8464
for symbol in message:
8565
if symbol in SYMBOLS:
8666
symIndex = SYMBOLS.find(symbol)
@@ -98,6 +78,26 @@ def get_random_key() -> int:
9878
return keyA * len(SYMBOLS) + keyB
9979

10080

81+
def main() -> None:
82+
"""
83+
>>> key = get_random_key()
84+
>>> msg = "This is a test!"
85+
>>> decrypt_message(key, encrypt_message(key, msg)) == msg
86+
True
87+
"""
88+
message = input("Enter message: ").strip()
89+
key = int(input("Enter key [2000 - 9000]: ").strip())
90+
mode = input("Encrypt/Decrypt [E/D]: ").strip().lower()
91+
92+
if mode.startswith("e"):
93+
mode = "encrypt"
94+
translated = encrypt_message(key, message)
95+
elif mode.startswith("d"):
96+
mode = "decrypt"
97+
translated = decrypt_message(key, message)
98+
print(f"\n{mode.title()}ed text: \n{translated}")
99+
100+
101101
if __name__ == "__main__":
102102
import doctest
103103

ciphers/atbash.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,6 @@ def benchmark() -> None:
6161

6262

6363
if __name__ == "__main__":
64-
for sequence in ("ABCDEFGH", "123GGjj", "testStringtest", "with space"):
65-
print(f"{sequence} encrypted in atbash: {atbash(sequence)}")
64+
for example in ("ABCDEFGH", "123GGjj", "testStringtest", "with space"):
65+
print(f"{example} encrypted in atbash: {atbash(example)}")
6666
benchmark()

ciphers/base32.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import base64
22

33

4-
def main():
4+
def main() -> None:
55
inp = input("->")
66
encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object)
77
b32encoded = base64.b32encode(encoded) # b32encoded the encoded string

ciphers/base85.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import base64
22

33

4-
def main():
4+
def main() -> None:
55
inp = input("->")
66
encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object)
77
a85encoded = base64.a85encode(encoded) # a85encoded the encoded string

ciphers/beaufort_cipher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def original_text(cipher_text: str, key_new: str) -> str:
6666
return or_txt
6767

6868

69-
def main():
69+
def main() -> None:
7070
message = "THE GERMAN ATTACK"
7171
key = "SECRET"
7272
key_new = generate_key(message, key)

ciphers/brute_force_caesar_cipher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def decrypt(message: str) -> None:
4343
print(f"Decryption using Key #{key}: {translated}")
4444

4545

46-
def main():
46+
def main() -> None:
4747
message = input("Encrypted message: ")
4848
message = message.upper()
4949
decrypt(message)

ciphers/cryptomath_module.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ def gcd(a: int, b: int) -> int:
44
return b
55

66

7-
def findModInverse(a: int, m: int) -> int:
7+
def find_mod_inverse(a: int, m: int) -> int:
88
if gcd(a, m) != 1:
9-
return None
9+
raise ValueError(f"mod inverse of {a!r} and {m!r} does not exist")
1010
u1, u2, u3 = 1, 0, a
1111
v1, v2, v3 = 0, 1, m
1212
while v3 != 0:

ciphers/decrypt_caesar_with_chi_squared.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#!/usr/bin/env python3
22

3-
from typing import Tuple
3+
from typing import Optional
44

55

66
def decrypt_caesar_with_chi_squared(
77
ciphertext: str,
8-
cipher_alphabet: str = None,
9-
frequencies_dict: str = None,
8+
cipher_alphabet: Optional[list[str]] = None,
9+
frequencies_dict: Optional[dict[str, float]] = None,
1010
case_sensetive: bool = False,
11-
) -> Tuple[int, float, str]:
11+
) -> tuple[int, float, str]:
1212
"""
1313
Basic Usage
1414
===========
@@ -123,9 +123,9 @@ def decrypt_caesar_with_chi_squared(
123123
AttributeError: 'int' object has no attribute 'lower'
124124
"""
125125
alphabet_letters = cipher_alphabet or [chr(i) for i in range(97, 123)]
126-
frequencies_dict = frequencies_dict or {}
127126

128-
if frequencies_dict == {}:
127+
# If the argument is None or the user provided an empty dictionary
128+
if not frequencies_dict:
129129
# Frequencies of letters in the english language (how much they show up)
130130
frequencies = {
131131
"a": 0.08497,
@@ -163,7 +163,7 @@ def decrypt_caesar_with_chi_squared(
163163
ciphertext = ciphertext.lower()
164164

165165
# Chi squared statistic values
166-
chi_squared_statistic_values = {}
166+
chi_squared_statistic_values: dict[int, tuple[float, str]] = {}
167167

168168
# cycle through all of the shifts
169169
for shift in range(len(alphabet_letters)):
@@ -215,22 +215,22 @@ def decrypt_caesar_with_chi_squared(
215215
chi_squared_statistic += chi_letter_value
216216

217217
# Add the data to the chi_squared_statistic_values dictionary
218-
chi_squared_statistic_values[shift] = [
218+
chi_squared_statistic_values[shift] = (
219219
chi_squared_statistic,
220220
decrypted_with_shift,
221-
]
221+
)
222222

223223
# Get the most likely cipher by finding the cipher with the smallest chi squared
224224
# statistic
225-
most_likely_cipher = min(
225+
most_likely_cipher: int = min(
226226
chi_squared_statistic_values, key=chi_squared_statistic_values.get
227-
)
227+
) # type: ignore # First argument to `min` is not optional
228228

229229
# Get all the data from the most likely cipher (key, decoded message)
230-
most_likely_cipher_chi_squared_value = chi_squared_statistic_values[
231-
most_likely_cipher
232-
][0]
233-
decoded_most_likely_cipher = chi_squared_statistic_values[most_likely_cipher][1]
230+
(
231+
most_likely_cipher_chi_squared_value,
232+
decoded_most_likely_cipher,
233+
) = chi_squared_statistic_values[most_likely_cipher]
234234

235235
# Return the data on the most likely shift
236236
return (

ciphers/diffie.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
def find_primitive(n: int) -> int:
1+
from typing import Optional
2+
3+
4+
def find_primitive(n: int) -> Optional[int]:
25
for r in range(1, n):
36
li = []
47
for x in range(n - 1):
@@ -8,18 +11,22 @@ def find_primitive(n: int) -> int:
811
li.append(val)
912
else:
1013
return r
14+
return None
1115

1216

1317
if __name__ == "__main__":
1418
q = int(input("Enter a prime number q: "))
1519
a = find_primitive(q)
16-
a_private = int(input("Enter private key of A: "))
17-
a_public = pow(a, a_private, q)
18-
b_private = int(input("Enter private key of B: "))
19-
b_public = pow(a, b_private, q)
20+
if a is None:
21+
print(f"Cannot find the primitive for the value: {a!r}")
22+
else:
23+
a_private = int(input("Enter private key of A: "))
24+
a_public = pow(a, a_private, q)
25+
b_private = int(input("Enter private key of B: "))
26+
b_public = pow(a, b_private, q)
2027

21-
a_secret = pow(b_public, a_private, q)
22-
b_secret = pow(a_public, b_private, q)
28+
a_secret = pow(b_public, a_private, q)
29+
b_secret = pow(a_public, b_private, q)
2330

24-
print("The key value generated by A is: ", a_secret)
25-
print("The key value generated by B is: ", b_secret)
31+
print("The key value generated by A is: ", a_secret)
32+
print("The key value generated by B is: ", b_secret)

0 commit comments

Comments
 (0)