import numpy as np def hill_en(ptext, hk): # all letters to uppercase ptext = ''.join(c.upper() for c in ptext if c.isalpha()) # matrix size n = int(len(hk)**0.5) # key matrix key = np.array([ord(c) - 65 for c in hk]).reshape(n, n) # padding ptext += 'X' * (-len(ptext) % n) # block operation result = "" for i in range(0, len(ptext), n): block = np.array([ord(c) - 65 for c in ptext[i:i+n]]) encrypted_block = (key @ block) % 26 result += ''.join(chr(val + 65) for val in encrypted_block) return result def hill_de(ctext, hk): # matrix size n = int(len(hk)**0.5) # key matrix and its inverse key = np.array([ord(c) - 65 for c in hk]).reshape(n, n) inv_key = np.linalg.inv(key).astype(int) % 26 # block operation result = "" for i in range(0, len(ctext), n): block = np.array([ord(c) - 65 for c in ctext[i:i+n]]) decrypted_block = (inv_key @ block) % 26 result += ''.join(chr(val + 65) for val in decrypted_block) return result def main(): ptext = input("Plaintext: ") hk = input("Hill Key: ") ctext = hill_en(ptext, hk) print(f"Ciphertext: {ctext}") print(f"Decrypted: {hill_de(ctext, hk)}") if __name__ == '__main__': main()