[python implements Hill encryption] the most detailed explanation of hill encryption, with code attached

Posted by xydra on Tue, 04 Jan 2022 01:03:25 +0100

preface

Recently, when I was preparing for the final exam of network security and reviewed Hill encryption, I remembered that the programming homework I had done before was rough, and I didn't understand how to find the decryption key of hill cryptosystem. Today, I figured it out, so I implemented and sorted out the hill cryptosystem. The code is attached for your reference and study.

1, Hill encryption Basics

1. Hill cipher is a multi table substitution cipher based on linear algebra.

Briefly describe the principle of Hill cryptosystem. For an input plaintext plaintext plaintext = 'Hello world!', First convert the plaintext into a numerical matrix P, which needs to be indexed by itself. For example, the character H is represented by 1... Then give an encryption key matrix K. through the encryption formula, an encrypted numerical matrix C can be obtained. Through the decryption formula, a decrypted numerical matrix P can be obtained. Finally, map P back to the form of characters, Use your own index to map the numerical matrix into string plaintext.

Because the decryption key of the Hill cryptosystem is obtained by some transformation of the encryption key, the Hill cryptosystem is a symmetric password.

2. Formula of hill cipher encryption and decryption:

Encryption formula:
C = K P m o d 26 (1) C=KPmod26 \tag{1} C=KPmod26(1)
Decryption formula:
P = K − 1 C m o d 26 (2) P=K^{-1}Cmod26 \tag{2} P=K−1Cmod26(2)
Where C represents plaintext, P represents ciphertext and matrix K K K represents encryption key, matrix K − 1 K^{-1} K − 1 indicates the decryption key. The difficulty of Hill password is to solve the decryption key.

3. Hill password decryption key K − 1 K^{-1} Formula of K − 1:

Decryption key of Hill password K − 1 K^{-1} K − 1 is not a simple pair K K K is inversed, but under module 26, right K K K inverse. At this time, the inverse formula has also changed.
K − 1 = d e t ( K ) − 1 ∗ K ∗ (1) K^{-1}=det(K)^{-1}*K^* \tag{1} K − 1=det(K) − 1 * k * (1) where K ∗ K^* K * yes K K The adjoint matrix of K, d e t ( K ) − 1 det(K)^{-1} det(K) − 1 yes K K The multiplicative inverse of the determinant value of K under module 26. For adjoint matrix K ∗ K^* The solution of K * is relatively easy. It is not difficult to find it by using the following formula. K ∗ = d e t ( K ) ∗ K − 1 (2) K^*=det(K)*K^{-1} \tag{2} K∗=det(K)∗K−1(2)

4. Find the multiplicative inverse of a number under modulus m:

The conditions to be satisfied by the multiplicative inverse element under module m are:
( x × y ) m o d m = 1 (3) (x×y)modm=1 \tag{3} (x×y)modm=1(3)

Note: not all numbers have multiplicative inverses under modulo 26.

# Finding the multiplicative inverse y of a number x under module 26 only needs to meet (x × y) mod 26 = 1
x = -939
# The value range of y is [0,26)
y = 0
while(y < 26):
    res = (x * y) % 26
    if res == 1:
        print(x,"The inverse of multiplication is:",y)
        break
    else:
        y = y + 1
        if y == 26:
            print(x,"Under module 26, there is no multiplicative inverse!")
5. Find the decryption key of Hill password K − 1 K^{-1} K−1:
import numpy as np
#This y is the multiplicative inverse of det(K) under module 26, which has been found to be 17, which is directly used here
y = 17
#K matrix
K = np.array([[17,17,5],[21,18,21],[2,2,19]], dtype=int)
# The inverse matrix K1 of K is obtained by inverting the K matrix
K1 = np.linalg.inv(K)
# Find the determinant value det(K) of K matrix
K_abs = np.linalg.det(K)
print("K The value of the determinant of is:",K_abs)
# Find the adjoint matrix of K matrix
K2 = K1 * K_abs  % 26
# Since the adjoint matrix may be a floating-point matrix, it needs to be rounded
# And cast each element member to an int type
K2 = np.around(K2)
K2 = K2.astype(np.int)
print("K The adjoint matrix is:\n",K2)
# Find the decryption key of Hill encryption
K3 = y * K2 % 26
print("Hill The decryption key of the password is:\n",K3)

Operation results:

K The value of the determinant of is -939.0
K The adjoint matrix is:
 [[14 25  7]
 [ 7  1  8]
 [ 6 26  1]]
Hill The decryption key of the password is:
 [[ 4  9 15]
 [15 17  6]
 [24  0 17]]

2, Hill encryption and decryption complete code

The code here does not assign an index to the letter, but directly uses the ascii code value of the letter as the index. In order to ensure the uniqueness of each letter after taking the module, the value of module m selected in the whole process is 256, that is, the following Hill encryption and decryption code is completed under module 256. Readers can also test under different module values according to their actual situation, or consider assigning an index to the letter.

import numpy as np

# Find the multiplicative inverse of any number under module m
def Multi_Inverse(x,m):
    # Input: find the multiplicative inverse of a number x under modulus m
    # The value range of y is [0,m)
    y = 0
    while(y < m):
        res = (x * y) % m
        if res == 1:
            print("In mold%d lower,The value of the encryption key determinant is%d,Its multiplicative inverse is%d" % (m,x,y))
            break
        else:
            y = y + 1
            if y == m:
                print(x,"In mold",m,"In this case, there is no multiplicative inverse!")
                return 0
    return y

# Find adjoint matrix
def Adjoint_Mat(K,K_det,m):
    # Input: matrix K, determinant value of matrix K_det, module m
    # The inverse matrix K1 of K is obtained by inverting the K matrix
    K1 = np.linalg.inv(K)
    # Find the adjoint matrix of K matrix
    K2 = K1 * K_det % m
    # Since the adjoint matrix may be a floating-point matrix, it needs to be rounded
    # And cast each element member to an int type
    K2 = np.around(K2)
    K2 = K2.astype(np.int)
    return K2

# Solving key k
def Decrypt_Key(K,m):
    # Find the determinant value det(K), module m of K matrix
    K_det = np.linalg.det(K)
    K2 = Adjoint_Mat(K, K_det, m)
    # Find the multiplicative inverse of det(K) under module 26
    y = Multi_Inverse(K_det, m)
    # Find the decryption key of Hill encryption
    K3 = y * K2 % m
    return K3

# Convert matrix (two-dimensional array) ascii code to character
def ascii2_char(array1):
    plaintext = ''
    row = array1.shape[0]
    col = array1.shape[1]
    for i in range(row):
        for j in range(col):
            plaintext = plaintext + chr(array1[i][j])
    return plaintext

# The plaintext is converted into ascii code value matrix, and the number of lines is consistent with the encryption key
def char2ascii2(plaintext,row,m):
    # Input: plaintext plaintext, row number of encryption matrix, modulus m
    l1 = [0,0,0]
    l2 = []
    for i in range(len(plaintext)):
        j = i % row
        if (i > 0 and i % row == 0):
            l2.append(l1)
            l1 = [0, 0, 0]
        l1[j] = ord(plaintext[i])
    l2.append(l1)
    m1 = np.array(l2)
    m1 = np.reshape(m1,(m1.shape[1],m1.shape[0]))
    m1 = m1 % m
    return m1

if __name__ == "__main__":
    # K matrix, i.e. encryption key
    K = np.array([[17,17,5],[21,18,21],[2,2,19]], dtype=int)
    # Decryption key k, modulus m
    m = 256
    k = Decrypt_Key(K,m)
    print("Hill The decryption key of the password is:\n",k)

    # Plaintext
    plaintext = 'Programming is a happy thing'
    print("Original plaintext content:\n",plaintext)

    # row number of encryption key matrix K
    row = K.shape[0]
    # The plaintext is converted into ascii code value matrix, and the number of lines is consistent with the encryption key
    # m1 is the plaintext ascii code value matrix
    m1 = char2ascii2(plaintext,row,m)

    # Encryption process, m2 is the encrypted matrix
    m2 = np.dot(K,m1) % 256
    Ciphertext = ascii2_char(m2)
    print("Ciphertext content:\n",Ciphertext)

    # Decryption process, m3 is the encrypted matrix
    m3 = np.dot(k,m2) % 256
    decrypt_text = ascii2_char(m3)
    print("Decryption result:\n", decrypt_text)

Operation results:

Under module 256,The value of the encryption key determinant is-939,Its multiplicative inverse is 253
Hill The decryption key of the password is:
 [[124 171 223]
 [ 47  85 244]
 [238   0 153]]
Original plaintext content:
 Programming is a happy thing
 Ciphertext content:
"d7´oæ¾PÜODO"¼
Decryption result:
 Programming is a happy thing  

Topics: Python Cyber Security