2323import numpy as np
2424from maths .greatest_common_divisor import greatest_common_divisor
2525
26+
2627class HillCipher :
2728 """
2829 Implementation of the Hill Cipher algorithm using matrix operations.
@@ -145,7 +146,7 @@ def check_determinant(self) -> None:
145146 """
146147 # 修复冗余的整数转换
147148 det = int (round (np .linalg .det (self .encrypt_key )))
148-
149+
149150 if det < 0 :
150151 det = det % len (self .key_string )
151152
@@ -183,15 +184,15 @@ def process_text(self, text: str) -> str:
183184 'ABCC'
184185 """
185186 chars = [char for char in text .upper () if char in self .key_string ]
186-
187+
187188 # Handle empty input case
188189 if not chars :
189190 return ""
190-
191+
191192 last = chars [- 1 ]
192193 while len (chars ) % self .break_key != 0 :
193194 chars .append (last )
194-
195+
195196 return "" .join (chars )
196197
197198 def encrypt (self , text : str ) -> str :
@@ -221,21 +222,21 @@ def encrypt(self, text: str) -> str:
221222 text = self .process_text (text .upper ())
222223 if not text :
223224 return ""
224-
225+
225226 encrypted = ""
226227
227228 for i in range (0 , len (text ) - self .break_key + 1 , self .break_key ):
228229 # Extract batch of characters
229230 batch = text [i : i + self .break_key ]
230-
231+
231232 # Convert to numerical vector
232233 vec = [self .replace_letters (char ) for char in batch ]
233234 batch_vec = np .array ([vec ]).T
234-
235+
235236 # Matrix multiplication and mod 36
236237 product = self .encrypt_key .dot (batch_vec )
237238 batch_encrypted = self .modulus (product ).T .tolist ()[0 ]
238-
239+
239240 # Convert back to characters
240241 encrypted_batch = "" .join (
241242 self .replace_digits (num ) for num in batch_encrypted
@@ -260,7 +261,7 @@ def make_decrypt_key(self) -> np.ndarray:
260261 >>> cipher.make_decrypt_key()
261262 array([[ 6, 25],
262263 [ 5, 26]])
263-
264+
264265 >>> key3x3 = np.array([[1,2,3],[4,5,6],[7,8,9]])
265266 >>> cipher3 = HillCipher(key3x3)
266267 >>> cipher3.make_decrypt_key() # Determinant 0 should be invalid
@@ -271,10 +272,10 @@ def make_decrypt_key(self) -> np.ndarray:
271272 """
272273 # 修复冗余的整数转换
273274 det = int (round (np .linalg .det (self .encrypt_key )))
274-
275+
275276 if det < 0 :
276277 det = det % len (self .key_string )
277-
278+
278279 det_inv : int | None = None
279280 for i in range (len (self .key_string )):
280281 if (det * i ) % len (self .key_string ) == 1 :
@@ -317,22 +318,22 @@ def decrypt(self, text: str) -> str:
317318 text = self .process_text (text .upper ())
318319 if not text :
319320 return ""
320-
321+
321322 decrypt_key = self .make_decrypt_key ()
322323 decrypted = ""
323324
324325 for i in range (0 , len (text ) - self .break_key + 1 , self .break_key ):
325326 # Extract batch of characters
326327 batch = text [i : i + self .break_key ]
327-
328+
328329 # Convert to numerical vector
329330 vec = [self .replace_letters (char ) for char in batch ]
330331 batch_vec = np .array ([vec ]).T
331-
332+
332333 # Matrix multiplication and mod 36
333334 product = decrypt_key .dot (batch_vec )
334335 batch_decrypted = self .modulus (product ).T .tolist ()[0 ]
335-
336+
336337 # Convert back to characters
337338 decrypted_batch = "" .join (
338339 self .replace_digits (num ) for num in batch_decrypted
@@ -345,7 +346,7 @@ def decrypt(self, text: str) -> str:
345346def main () -> None :
346347 """
347348 Command-line interface for Hill Cipher operations.
348-
349+
349350 Steps:
350351 1. User inputs encryption key size
351352 2. User inputs encryption key matrix rows
@@ -358,14 +359,14 @@ def main() -> None:
358359
359360 print ("Enter each row of the encryption key with space separated integers" )
360361 for i in range (n ):
361- 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 ()]
362363 hill_matrix .append (row )
363364
364365 hc = HillCipher (np .array (hill_matrix ))
365366
366367 print ("\n Would you like to encrypt or decrypt some text?" )
367368 option = input ("1. Encrypt\n 2. Decrypt\n Enter choice (1/2): " )
368-
369+
369370 if option == "1" :
370371 text = input ("\n Enter text to encrypt: " )
371372 print ("\n Encrypted text:" )
@@ -380,20 +381,21 @@ def main() -> None:
380381
381382if __name__ == "__main__" :
382383 import doctest
384+
383385 doctest .testmod ()
384-
386+
385387 print ("\n Running sample tests..." )
386388 key = np .array ([[2 , 5 ], [1 , 6 ]])
387389 cipher = HillCipher (key )
388-
390+
389391 # Test encryption/decryption round trip
390392 plaintext = "HELLO123"
391393 encrypted = cipher .encrypt (plaintext )
392394 decrypted = cipher .decrypt (encrypted )
393-
395+
394396 print (f"\n Original text: { plaintext } " )
395397 print (f"Encrypted text: { encrypted } " )
396398 print (f"Decrypted text: { decrypted } " )
397-
399+
398400 # Run CLI interface
399401 main ()
0 commit comments