Skip to content

Commit dd469e4

Browse files
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
1 parent e09fa4b commit dd469e4

1 file changed

Lines changed: 14 additions & 12 deletions

File tree

ciphers/hill_cipher.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import numpy as np
44
from maths.greatest_common_divisor import greatest_common_divisor
55

6+
67
class HillCipher:
78
key_string = string.ascii_uppercase + string.digits # 36 chars
89
modulus = np.vectorize(lambda x: x % 36) # Mod 36
@@ -26,15 +27,15 @@ def check_determinant(self) -> None:
2627
det = round(np.linalg.det(self.encrypt_key))
2728
if det < 0:
2829
det %= len(self.key_string)
29-
30+
3031
error_msg = f"Det {det} not coprime with 36. Try another key."
3132
if greatest_common_divisor(det, len(self.key_string)) != 1:
3233
raise ValueError(error_msg)
3334

3435
def process_text(self, text: str) -> str:
3536
"""Uppercase, filter, pad text"""
3637
chars = [c for c in text.upper() if c in self.key_string]
37-
last = chars[-1] if chars else 'A'
38+
last = chars[-1] if chars else "A"
3839
while len(chars) % self.break_key != 0:
3940
chars.append(last)
4041
return "".join(chars)
@@ -44,7 +45,7 @@ def encrypt(self, text: str) -> str:
4445
text = self.process_text(text.upper())
4546
encrypted = ""
4647
for i in range(0, len(text), self.break_key):
47-
batch = text[i:i+self.break_key]
48+
batch = text[i : i + self.break_key]
4849
vec = [self.replace_letters(c) for c in batch]
4950
batch_vec = np.array([vec]).T
5051
product = self.encrypt_key.dot(batch_vec)
@@ -61,15 +62,13 @@ def make_decrypt_key(self) -> np.ndarray:
6162
det = round(np.linalg.det(self.encrypt_key))
6263
if det < 0:
6364
det %= len(self.key_string)
64-
65+
6566
# Find det modular inverse
6667
det_inv = next(i for i in range(36) if (det * i) % 36 == 1)
67-
68+
6869
# Compute inverse key
6970
inv_key = (
70-
det_inv *
71-
np.linalg.det(self.encrypt_key) *
72-
np.linalg.inv(self.encrypt_key)
71+
det_inv * np.linalg.det(self.encrypt_key) * np.linalg.inv(self.encrypt_key)
7372
)
7473
return self.to_int(self.modulus(inv_key))
7574

@@ -79,7 +78,7 @@ def decrypt(self, text: str) -> str:
7978
text = self.process_text(text.upper())
8079
decrypted = ""
8180
for i in range(0, len(text), self.break_key):
82-
batch = text[i:i+self.break_key]
81+
batch = text[i : i + self.break_key]
8382
vec = [self.replace_letters(c) for c in batch]
8483
batch_vec = np.array([vec]).T
8584
product = decrypt_key.dot(batch_vec)
@@ -91,23 +90,26 @@ def decrypt(self, text: str) -> str:
9190
decrypted += decrypted_batch
9291
return decrypted
9392

93+
9494
def main() -> None:
9595
"""Hill Cipher CLI"""
9696
n = int(input("Enter key order: "))
9797
print(f"Enter {n} rows of space-separated integers:")
9898
matrix = [list(map(int, input().split())) for _ in range(n)]
99-
99+
100100
hc = HillCipher(np.array(matrix))
101-
101+
102102
option = input("1. Encrypt\n2. Decrypt\nChoose: ")
103103
text = input("Enter text: ")
104-
104+
105105
if option == "1":
106106
print("Encrypted:", hc.encrypt(text))
107107
elif option == "2":
108108
print("Decrypted:", hc.decrypt(text))
109109

110+
110111
if __name__ == "__main__":
111112
import doctest
113+
112114
doctest.testmod()
113115
main()

0 commit comments

Comments
 (0)