python多表代换密码实现&&模逆矩阵的求解

  • Post author:
  • Post category:python




加密部分

加密部分比较简单



字符生成数据

这里需要一个函数将输入的字符串转化为矩阵,方便后续计算,

l

参数为切割的长度,

因为输入字符不一定能被完整切割,所以在生成的矩阵最后一行对不足的补0


def gen_data(m,l=3):#将m生成定长的矩阵,每行为一个定长段
    m = m.replace(" ","").lower()#全部变成小写
    h = len(m)/l

    if int(h)<h:
        h = int(h)+1
    M = np.zeros([int(h),int(l)])
    #字符分成定长段
    textArr = re.findall('.{'+str(l)+'}', m)
    tem_text = m[(len(textArr)*l):]#防止添加空字符段
    if len(tem_text) >0:
        textArr.append(tem_text)
        
    for i in range(len(textArr)):
        tem = [ord(j) - 97 for j in textArr[i]]
#         print(tem)
        M[i] = np.pad(tem,(0,l-len(tem)))#最后一段数据不足时填充
    return M

对该函数进行测试,生成的数据会将空格清除,并且全部变为小写:

gen_data('asdafgrefgergk')
----------->>
array([[ 0., 18.,  3.],
       [ 0.,  5.,  6.],
       [17.,  4.,  5.],
       [ 6.,  4., 17.],
       [ 6., 10.,  0.]])



字符串加密

加密输入的参数A必须可逆

def gcd(a, b=26):
    while a != 0:
        a, b = b % a, a
    return b
def duobiaodaihuan_en(A,B,m,N=26,l=3):
    a = round(np.absolute(np.linalg.det(A)))
    if a==0:
        print('矩阵A不可逆')
        return None
    if int(gcd(a,N)) !=1:
        print("A与N 不满足gcd条件")
        return None
    #加密过程
    M = gen_data(m,l)
    C = (np.dot(A,M.T)+B)%N
    C = C.T.reshape(1,-1)#还是二维数组
    result = [chr(int(i+97)) for i in C[0]]
    return ''.join(result)

对该函数进行测试

A=np.array([[11,2,19],[5,23,25],[20,7,17]])#这个矩阵A是教材上提供的
B = np.random.randint(0,26,[3,1])#随机生成B
m = duobiaodaihuan_en(A,B,'YOUR PIN NO IS FOUR ONE TWO SIX')
m
-------->
'whefhftnnlidxudwctzqobsx'



解密部分



模逆运算

模逆矩阵的求法有点复杂,这里参考了哈其他博主的一些放法

def gcd(a, b=26):
    while a != 0:
        a, b = b % a, a
    return b

#矩阵A的模逆运算
def inv_A(A,N=26):
    det_inv = exgcd(int(round((det(a) % 26))), 26)
    tem_A = np.linalg.det(A)*np.linalg.inv(a)%N
    A_inv =tem_A*det_inv%N
    return A_inv

def exgcd(a, m):
    if gcd(a, m) != 1:
        return None
    u1, u2, u3 = 1, 0, a
    v1, v2, v3 = 0, 1, m
    while v3 != 0:
        q = u3 // v3
        v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
    return u1 % m

这个测试哈模逆矩阵


A = array([[11,  2, 19],
       [ 5, 23, 25],
       [20,  7, 17]])
       
inv_A(A)
------>
matrix([[10., 23.,  7.],
        [15.,  9., 22.],
        [ 5.,  9., 21.]])



字符解密

与加密类似,只要提前把需要的参数准备好参考教材上的公式就好了

def duobiaodaihuan_de(A,B,m,N=26,l=3):
    a = round(np.absolute(np.linalg.det(A)))
    if a==0:
        print('矩阵A不可逆')
        return None
    if int(gcd(a,N)) !=1:
        print("A与N 不满足gcd条件")
        return None
    #解密过程过程
    M = gen_data(m,l)
    C = np.dot(inv_A(A,N),M.T-B)%N
    C = C.T.reshape(1,-1)#还是二维数组
    
    result = [chr(int(round(i+97))) for i in np.array(C)[0]]#注意用round,不然回少一个值
    return ''.join(result)

测试上面加密的字符

duobiaodaihuan_de(A,B,m)
---->
'yourpinnoisfouronetwosix'



多表代换源码

#古典密码实现
import numpy as np
import re
def duobiaodaihuan_en(A,B,m,N=26,l=3):
    a = round(np.absolute(np.linalg.det(A)))
    if a==0:
        print('矩阵A不可逆')
        return None
    if int(gcd(a,N)) !=1:
        print("A与N 不满足gcd条件")
        return None
    #加密过程
    M = gen_data(m,l)
    C = (np.dot(A,M.T)+B)%N
    C = C.T.reshape(1,-1)#还是二维数组
    result = [chr(int(i+97)) for i in C[0]]
    return ''.join(result)
def duobiaodaihuan_de(A,B,m,N=26,l=3):
    a = round(np.absolute(np.linalg.det(A)))
    if a==0:
        print('矩阵A不可逆')
        return None
    if int(gcd(a,N)) !=1:
        print("A与N 不满足gcd条件")
        return None
    #解密过程过程
    M = gen_data(m,l)
    C = np.dot(inv_A(A,N),M.T-B)%N
    C = C.T.reshape(1,-1)#还是二维数组
    
    result = [chr(int(round(i+97))) for i in np.array(C)[0]]#注意用round,不然回少一个值
    return ''.join(result)
    
def gcd(a, b=26):
    while a != 0:
        a, b = b % a, a
    return b

#矩阵A的模逆运算
def inv_A(A,N=26):
    det_inv = exgcd(int(round((det(a) % 26))), 26)
    tem_A = np.linalg.det(A)*np.linalg.inv(a)%N
    A_inv =tem_A*det_inv%N
    return A_inv

def exgcd(a, m):
    if gcd(a, m) != 1:
        return None
    u1, u2, u3 = 1, 0, a
    v1, v2, v3 = 0, 1, m
    while v3 != 0:
        q = u3 // v3
        v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
    return u1 % m

def gen_data(m,l=3):#将m生成定长的矩阵,每行为一个定长段
    m = m.replace(" ","").lower()#全部变成小写
    h = len(m)/l

    if int(h)<h:
        h = int(h)+1
    M = np.zeros([int(h),int(l)])
    #字符分成定长段
    textArr = re.findall('.{'+str(l)+'}', m)
    tem_text = m[(len(textArr)*l):]#防止添加空字符段
    if len(tem_text) >0:
        textArr.append(tem_text)
        
    for i in range(len(textArr)):
        tem = [ord(j) - 97 for j in textArr[i]]
#         print(tem)
        M[i] = np.pad(tem,(0,l-len(tem)))#最后一段数据不足时填充
    return M

A=np.array([[11,2,19],[5,23,25],[20,7,17]])
B = np.random.randint(0,26,[3,1])
m = duobiaodaihuan_en(A,B,'YOUR PIN NO IS FOUR ONE TWO SIX')
print(f"加密:{m}")
c = duobiaodaihuan_de(A,B,m)
print(f"解密:{c}")



版权声明:本文为qq_45458674原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。