1919"""
2020
2121import string
22- from typing import Optional
23-
2422import numpy as np
25-
2623from maths .greatest_common_divisor import greatest_common_divisor
2724
2825
@@ -136,25 +133,27 @@ def check_determinant(self) -> None:
136133 >>> HillCipher(invalid_key) # Determinant 0
137134 Traceback (most recent call last):
138135 ...
139- ValueError: determinant modular 36 of encryption key(0) is not co prime w.r.t 36.
140- Try another key.
136+ ValueError: determinant modular 36 of encryption key(0) is not co prime
137+ w.r.t 36. Try another key.
141138
142139 >>> invalid_key2 = np.array([[4, 2], [6, 3]])
143140 >>> HillCipher(invalid_key2) # Determinant 0
144141 Traceback (most recent call last):
145142 ...
146- ValueError: determinant modular 36 of encryption key(0) is not co prime w.r.t 36.
147- Try another key.
143+ ValueError: determinant modular 36 of encryption key(0) is not co prime
144+ w.r.t 36. Try another key.
148145 """
149- det = int (round (np .linalg .det (self .encrypt_key )))
146+ det = round (np .linalg .det (self .encrypt_key ))
147+ det = int (det ) # Convert to int after rounding float
148+
150149 if det < 0 :
151150 det = det % len (self .key_string )
152151
153152 req_l = len (self .key_string )
154153 if greatest_common_divisor (det , req_l ) != 1 :
155154 msg = (
156- f"determinant modular { req_l } of encryption key({ det } ) "
157- f"is not co prime w.r.t { req_l } .\n Try another key."
155+ f"determinant modular { req_l } of encryption key({ det } ) is not co prime "
156+ f"w.r.t { req_l } .\n Try another key."
158157 )
159158 raise ValueError (msg )
160159
@@ -184,15 +183,15 @@ def process_text(self, text: str) -> str:
184183 'ABCC'
185184 """
186185 chars = [char for char in text .upper () if char in self .key_string ]
187-
186+
188187 # Handle empty input case
189188 if not chars :
190189 return ""
191-
190+
192191 last = chars [- 1 ]
193192 while len (chars ) % self .break_key != 0 :
194193 chars .append (last )
195-
194+
196195 return "" .join (chars )
197196
198197 def encrypt (self , text : str ) -> str :
@@ -222,21 +221,21 @@ def encrypt(self, text: str) -> str:
222221 text = self .process_text (text .upper ())
223222 if not text :
224223 return ""
225-
224+
226225 encrypted = ""
227226
228227 for i in range (0 , len (text ) - self .break_key + 1 , self .break_key ):
229228 # Extract batch of characters
230229 batch = text [i : i + self .break_key ]
231-
230+
232231 # Convert to numerical vector
233232 vec = [self .replace_letters (char ) for char in batch ]
234233 batch_vec = np .array ([vec ]).T
235-
234+
236235 # Matrix multiplication and mod 36
237236 product = self .encrypt_key .dot (batch_vec )
238237 batch_encrypted = self .modulus (product ).T .tolist ()[0 ]
239-
238+
240239 # Convert back to characters
241240 encrypted_batch = "" .join (
242241 self .replace_digits (num ) for num in batch_encrypted
@@ -245,6 +244,7 @@ def encrypt(self, text: str) -> str:
245244
246245 return encrypted
247246
247+
248248 def make_decrypt_key (self ) -> np .ndarray :
249249 """
250250 Compute decryption key matrix from encryption key.
@@ -261,20 +261,22 @@ def make_decrypt_key(self) -> np.ndarray:
261261 >>> cipher.make_decrypt_key()
262262 array([[ 6, 25],
263263 [ 5, 26]])
264-
264+
265265 >>> key3x3 = np.array([[1,2,3],[4,5,6],[7,8,9]])
266266 >>> cipher3 = HillCipher(key3x3)
267267 >>> cipher3.make_decrypt_key() # Determinant 0 should be invalid
268268 Traceback (most recent call last):
269269 ...
270- ValueError: determinant modular 36 of encryption key(0) is not co prime w.r.t 36.
271- Try another key.
270+ ValueError: determinant modular 36 of encryption key(0) is not co prime
271+ w.r.t 36. Try another key.
272272 """
273- det = int (round (np .linalg .det (self .encrypt_key )))
273+ det = round (np .linalg .det (self .encrypt_key ))
274+ det = int (det ) # Convert to int after rounding float
275+
274276 if det < 0 :
275277 det = det % len (self .key_string )
276-
277- det_inv : Optional [ int ] = None
278+
279+ det_inv : int | None = None
278280 for i in range (len (self .key_string )):
279281 if (det * i ) % len (self .key_string ) == 1 :
280282 det_inv = i
@@ -316,22 +318,22 @@ def decrypt(self, text: str) -> str:
316318 text = self .process_text (text .upper ())
317319 if not text :
318320 return ""
319-
321+
320322 decrypt_key = self .make_decrypt_key ()
321323 decrypted = ""
322324
323325 for i in range (0 , len (text ) - self .break_key + 1 , self .break_key ):
324326 # Extract batch of characters
325327 batch = text [i : i + self .break_key ]
326-
328+
327329 # Convert to numerical vector
328330 vec = [self .replace_letters (char ) for char in batch ]
329331 batch_vec = np .array ([vec ]).T
330-
332+
331333 # Matrix multiplication and mod 36
332334 product = decrypt_key .dot (batch_vec )
333335 batch_decrypted = self .modulus (product ).T .tolist ()[0 ]
334-
336+
335337 # Convert back to characters
336338 decrypted_batch = "" .join (
337339 self .replace_digits (num ) for num in batch_decrypted
@@ -344,7 +346,7 @@ def decrypt(self, text: str) -> str:
344346def main () -> None :
345347 """
346348 Command-line interface for Hill Cipher operations.
347-
349+
348350 Steps:
349351 1. User inputs encryption key size
350352 2. User inputs encryption key matrix rows
@@ -357,14 +359,14 @@ def main() -> None:
357359
358360 print ("Enter each row of the encryption key with space separated integers" )
359361 for i in range (n ):
360- row = [int (x ) for x in input (f"Row { i + 1 } : " ).split ()]
362+ row = [int (x ) for x in input (f"Row { i + 1 } : " ).split ()]
361363 hill_matrix .append (row )
362364
363365 hc = HillCipher (np .array (hill_matrix ))
364366
365367 print ("\n Would you like to encrypt or decrypt some text?" )
366368 option = input ("1. Encrypt\n 2. Decrypt\n Enter choice (1/2): " )
367-
369+
368370 if option == "1" :
369371 text = input ("\n Enter text to encrypt: " )
370372 print ("\n Encrypted text:" )
@@ -379,21 +381,20 @@ def main() -> None:
379381
380382if __name__ == "__main__" :
381383 import doctest
382-
383384 doctest .testmod ()
384-
385+
385386 print ("\n Running sample tests..." )
386387 key = np .array ([[2 , 5 ], [1 , 6 ]])
387388 cipher = HillCipher (key )
388-
389+
389390 # Test encryption/decryption round trip
390391 plaintext = "HELLO123"
391392 encrypted = cipher .encrypt (plaintext )
392393 decrypted = cipher .decrypt (encrypted )
393-
394+
394395 print (f"\n Original text: { plaintext } " )
395396 print (f"Encrypted text: { encrypted } " )
396397 print (f"Decrypted text: { decrypted } " )
397-
398+
398399 # Run CLI interface
399400 main ()
0 commit comments