Hill Cipher

Another interesting multi letter cipher is the Hill cipher, developed by the mathematician Lester Hill in 1929.

THE HILL ALGORITHM 

This encryption algorithm takes n successive plaintext letters and substitutes for them n ciphertext letters. The substitution is determined by linear equations in which each character is assigned a numerical value (a=0,b=1,,z=25)

C=KP, where  K is the key matrix and P is the plaintext vector

P=K1C, where K1 is the inverse of key matrix K in (mod26)

How the Hill Cipher Works
  1. Key Matrix:

    • Choose a key matrix K of size n×n (e.g., 2×2, 3×3).
    • The key matrix should be invertible modulo 26 (the number of letters in the English alphabet).
  2. Plaintext Preparation:

    • Convert the plaintext into vectors of size n.
    • If the plaintext length is not a multiple of n, pad it with extra letters (e.g., 'X').
  3. Encryption:

    • Multiply the key matrix K by each plaintext vector, and take the result modulo 26 to get the ciphertext vector.
    • Convert the resulting numbers back into letters.
  4. Decryption:

    • Calculate the inverse of the key matrix K1 modulo 26.
    • Multiply the inverse matrix by each ciphertext vector, and take the result modulo 26 to get the plaintext vector.
    • Convert the resulting numbers back into letters.

Example

Let's encrypt the plaintext "HELP" using a 2×2 key matrix.

Step 1: Key Matrix

Choose the key matrix: K=[3325]

Step 2: Plaintext Preparation

Convert "HELP" into numbers: H=7, E=4, L=11, P=15

Since our key matrix is 2×2, divide the plaintext into pairs:

  • (H, E) -> (7, 4)
  • (L, P) -> (11, 15)

Step 3: Encryption

Encrypt each pair using matrix multiplication and take modulo 26.

For (H, E): [3325][74]=[37+3427+54]=[21+1214+20]=[3334]

Take modulo 26: [3334][78](mod26)

Convert back to letters: (7, 8) -> HI

For (L, P): [3325][1115]=[311+315211+515]=[33+4522+75]=[7897]

Take modulo 26: [7897][019](mod26)

Convert back to letters: (0, 19) -> AT

So, the ciphertext for "HELP" is "HIAT"

Step 4: Decryption

To decrypt, we need the inverse of the key matrix modulo 26.

Find the determinant of K: det(K)=3532=156=9

Find the modular inverse of the determinant modulo 26, which is 3 (since 9×31(mod26)

Compute the inverse matrix: K1=19[5323]3[5323][15969][1517209](mod26)

Decrypt the ciphertext "HIAT" using  K1

  • Convert "HIAT" to numbers: H=7, I=8, A=0, T=19

For (H, I): [1517209][78]=[157+178207+98]=[105+136140+72]=[241212]

Take modulo 26: [241212][74](mod26)

Convert back to letters: (7, 4) -> HE

For (A, T): [1517209][019]=[150+1719200+919]=[0+3230+171]=[323171]

Take modulo 26: [323171][1115](mod26)

Convert back to letters: (11, 15) -> LP

The decrypted plaintext is "HELP".

Python Code Hill Cipher

import numpy as np

def mod_inverse(a, m):
    # Find modular inverse using extended Euclidean algorithm
    m0, x0, x1 = m, 0, 1
    if m == 1:
        return 0
    while a > 1:
        # q is quotient
        q = a // m
        m, a = a % m, m
        x0, x1 = x1 - q * x0, x0
    if x1 < 0:
        x1 += m0
    return x1

def matrix_mod_inverse(matrix, modulus):
    det = int(np.round(np.linalg.det(matrix)))
    det_inv = mod_inverse(det % modulus, modulus)
    matrix_mod_inv = det_inv * np.round(det * np.linalg.inv(matrix)).astype(int) % modulus
    return matrix_mod_inv

def encrypt(plaintext, key):
    key_matrix = np.array(key)
    plaintext_numbers = [ord(char) - ord('A') for char in plaintext.upper() if char.isalpha()]

    # Pad with 'X' if necessary
    if len(plaintext_numbers) % 2 != 0:
        plaintext_numbers.append(ord('X') - ord('A'))

    ciphertext = ''
    for i in range(0, len(plaintext_numbers), 2):
        vector = np.array(plaintext_numbers[i:i+2])
        encrypted_vector = np.dot(key_matrix, vector) % 26
        ciphertext += ''.join(chr(num + ord('A')) for num in encrypted_vector)
    
    return ciphertext

def decrypt(ciphertext, key):
    key_matrix = np.array(key)
    key_matrix_inv = matrix_mod_inverse(key_matrix, 26)
    ciphertext_numbers = [ord(char) - ord('A') for char in ciphertext.upper() if char.isalpha()]

    plaintext = ''
    for i in range(0, len(ciphertext_numbers), 2):
        vector = np.array(ciphertext_numbers[i:i+2])
        decrypted_vector = np.dot(key_matrix_inv, vector) % 26
        plaintext += ''.join(chr(int(num) + ord('A')) for num in decrypted_vector)

    return plaintext

# Example usage
key = [[3, 3], [2, 5]]
plaintext = "HELP"
ciphertext = encrypt(plaintext, key)
decrypted_text = decrypt(ciphertext, key)

print(f"Plaintext: {plaintext}")
print(f"Ciphertext: {ciphertext}")
print(f"Decrypted: {decrypted_text}")

Output:
Plaintext: HELP
Ciphertext: HIAT
Decrypted: HELP

Encrypt the text "cryptography" using HillCipher with key 
K=[5794] (University Question)
Plaintext: CRYPTOGRAPHY
Ciphertext: ZIRQLTTSBIVD

Comments

Popular posts from this blog

Cryptographic Algorithms CST 393 KTU CS Honour Notes Semester V -Dr Binu V P

OSI Security Architecture

Data Encryption Standard - DES Algorithm