Hill Cipher
Hill Cipher
Program:
import numpy as np
# Convert letters to numbers (A=0, B=1, ..., Z=25)
def letter_to_number(letter):
return ord(letter.upper()) - ord('A')
# Convert numbers to letters (0=A, 1=B, ..., 25=Z)
def number_to_letter(number):
return chr(number + ord('A'))
# Prepare the message: split into pairs and pad if necessary
def prepare_message(message, block_size):
message = message.replace(" ", "").upper()
if len(message) % block_size != 0:
message += 'X' * (block_size - len(message) % block_size) # Padding with 'X'
return message
# Encrypt a block of letters using the key matrix
def encrypt_block(block, key_matrix):
block_vector = np.array([letter_to_number(c) for c in block])
encrypted_vector = np.dot(key_matrix, block_vector) % 26 # Mod 26 arithmetic
return ''.join(number_to_letter(num) for num in encrypted_vector)
# Decrypt a block of letters using the inverse key matrix
def decrypt_block(block, inverse_key_matrix):
block_vector = np.array([letter_to_number(c) for c in block])
decrypted_vector = np.dot(inverse_key_matrix, block_vector) % 26 # Mod 26 arithmetic
return ''.join(number_to_letter(num) for num in decrypted_vector)
# Find modular inverse of a matrix (mod 26)
def mod_matrix_inverse(matrix, modulus):
det = int(np.round(np.linalg.det(matrix))) # Determinant of the matrix
det_inv = pow(det, -1, modulus) # Modular inverse of determinant
matrix_mod_inv = det_inv * np.round(det * np.linalg.inv(matrix)).astype(int) % modulus
return matrix_mod_inv
# Hill cipher encryption function
def hill_cipher_encrypt(message, key_matrix):
block_size = key_matrix.shape[0]
message = prepare_message(message, block_size)
encrypted_message = ""
for i in range(0, len(message), block_size):
block = message[i:i+block_size]
encrypted_message += encrypt_block(block, key_matrix)
return encrypted_message
# Hill cipher decryption function
def hill_cipher_decrypt(ciphertext, key_matrix):
block_size = key_matrix.shape[0]
inverse_key_matrix = mod_matrix_inverse(key_matrix, 26)
decrypted_message = ""
for i in range(0, len(ciphertext), block_size):
block = ciphertext[i:i+block_size]
decrypted_message += decrypt_block(block, inverse_key_matrix)
return decrypted_message
# Example usage:
# 2x2 key matrix for encryption (must be invertible mod 26)
key_matrix = np.array([[3, 3], [2, 5]])
message = "Prashik Xncoder"
encrypted_message = hill_cipher_encrypt(message, key_matrix)
print(f"Encrypted message: {encrypted_message}")
decrypted_message = hill_cipher_decrypt(encrypted_message, key_matrix)
print(f"Decrypted message: {decrypted_message}")
Output: