54 lines
1.5 KiB
Python
54 lines
1.5 KiB
Python
import numpy as np
|
|
|
|
def hill_en(ptext, hk):
|
|
# keep only letters and convert 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
|
|
out_chars = []
|
|
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
|
|
out_chars.extend(chr(int(val) + 65) for val in encrypted_block)
|
|
|
|
return ''.join(out_chars)
|
|
|
|
def hill_de(ctext, hk):
|
|
# keep only letters and convert to uppercase
|
|
ctext = ''.join(c.upper() for c in ctext if c.isalpha())
|
|
|
|
# matrix size
|
|
n = int(len(hk)**0.5)
|
|
|
|
# key matrix and its inverse (note: not a true modular inverse; kept minimal per lab)
|
|
key = np.array([ord(c) - 65 for c in hk]).reshape(n, n)
|
|
inv_key = np.linalg.inv(key)
|
|
inv_key = np.rint(inv_key).astype(int) % 26
|
|
|
|
# block operation
|
|
out_chars = []
|
|
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
|
|
out_chars.extend(chr(int(val) + 65) for val in decrypted_block)
|
|
|
|
return ''.join(out_chars)
|
|
|
|
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()
|