三种古典密码

隐身守侯 提交于 2019-12-05 20:02:03

单表代替密码

仿射密码

仿射密码为单表代替密码,26个字母对应不同的数值,简单来说就是加法密码和乘法密码的结合,当下面式子中的a=1时就是凯撒密码了

A B C D E F G H I J K L M
0 1 2 3 4 5 6 7 8 9 10 11 12
N O P Q R S T U V W X Y Z
13 14 15 16 17 18 19 20 21 22 23 24 25

密码体制的五元组:{P、C、K、E、D}

对于仿射密码而言:
\[ P=C=Z_{26} \]

\[ K=\{(a,b) \in Z_{26}\times Z_{26}:gcd(a,26)=1\} \]

对于任意的\(k=(a,b) \in K,X,Y \in Z_{26}\)

\[ 加密:e_{k}(X)=(aX+b) \quad mod \quad 26 \]

\[ 解密:d_{k}(Y)=a^{-1}(Y-b) \quad mod \quad 26 \]

其中\(a^-1\)是a关于模26乘法的逆,即\(a \times b \quad mod \quad 26=1\)

实例

K=(3,7),加密"You are beautiful"

# encoding="utf-8"
# @yoloyanng

#求乘法逆元
def get(a,b):
    if b==0:
        return 1,0
    else:
        k=a//b
        remainder = a % b
        x1,y1=get(b,remainder)
        x,y=y1,x1-k*y1
        return x,y

#加密函数
def encrypt(str1,a,b):
    private_data=""
    for i in str1:
        if(ord(i)>=97 and ord(i)<=122):
            cipher=((ord(i)-97)*a+b)%26
            i=chr(cipher+97)
        elif(ord(i)>=65 and ord(i)<=90):
            cipher=((ord(i)-65)*a+b)%26
            i=chr(cipher+65)
        else:
            i=i
        private_data+=i
    return private_data

#解密函数
def decrypt(str2,a_1,b):
    public_data=""
    for i in str2:
        if(ord(i)>=97 and ord(i)<=122):
            temp = a_1*(ord(i)-97-b) % 26
            i=chr(temp+97)
        elif(ord(i)>=65 and ord(i)<=90):
            temp = a_1*(ord(i)-65-b) % 26
            i=chr(temp+65)
        else:
            i=i
        public_data+=i
    return public_data


if __name__ == '__main__':
    a=5
    b=8
    a_1,y=get(a,26)
    str1="You are beautiful"
    miwen=encrypt(str1,a,b)
    mingwen=decrypt(miwen,a_1,b)
    print(miwen)
    print(mingwen)

多表代替密码

希尔密码

对于密码体制的五元组(P、C、K、E、D)有

  • \(P=C=(Z_{26})^m\),m是一个不小于2的整数

  • K是定义在\(Z_{26}\)上的\(m \times m\)可逆矩阵的集合,且集合中的元素的行列式与26互素

  • 取密钥\(k \in K\),k为一个\(m \times m\)矩阵,记为\((k_{ij})\),对:
    \[ x=(x_1,x_2,···,x_m) \in P,y=(y_1,y_2,···,y_m) \in C \]
    定义:
    \[ 加密:e_k(x)=k\times x \quad mod \quad 26 \]

    \[ 解密:d_k(y)=k^{-1} \times y\quad mod \quad 26 \]

    \(k^{-1}\)为k的逆矩阵

实例

明文:yoloyanng

加密

将明文分成三个字母组成的分组 yol oya nng,得到
\[ x_1=(24,14,11)^ T、x_2=(14,24,0)^T、x_3=(13,13,6)^T \]
所以:
\[ (y_1,y_2,y_3)=(x_1,x_2,x_3) \times k \]
即:
\[ y_1= k\times x_1=(7,15,11)^T、y_2= k \times x_2 =(20,24,6)^T、y_3=k \times x_3=(23,20,11)^T \]
所以得到密文为:hpluygxul

解密

计算k的模逆矩阵与密文相乘即可得到密文,具体略

Python:

import numpy as np
from libnum import *


# 转换为对应数字
def transform(string, size):
    string = string.lower()
    blocks = [string[i:i + size] for i in range(0, len(string), size)]

    # 将 a-z 编码为 0-25
    temp = np.mat([list(map(ord, block)) for block in blocks]) - ord('a')
    return temp % 26


# 加密
def Encrypt(m, k, size):
    # 加密矩阵
    c = ""
    m_num = transform(m, size)
    temp = [(np.dot(k, i.T) % 26) for i in m_num]
    for j in temp:
        for t in range(3):
            c = c + chr(j[t, 0] + ord('a'))
    return c


# 解密
def Decrypt(c, k, size):
    m = ""
    # 计算行列式
    detk = np.linalg.det(k)
    # 计算逆矩阵
    k_inv = np.linalg.inv(k)
    # 求伴随矩阵
    k_con = detk * k_inv % 26
    k_1 = invmod(round(detk), 26) * k_con % 26
    c_num = transform(c, size)
    temp = [(np.dot(k_1, i.T) % 26) for i in c_num]
    for j in temp:
        for t in range(3):
            m = m + chr(int(round(j[t, 0])) + ord('a'))
    return m


if __name__ == '__main__':
    main()

维吉尼亚密码

对于密码体制的五元组(P、C、K、E、D)有

  • \(P=C=K=(Z_{26})^m\),m是一个正整数

  • 对于任意的\(k=(k_1,k_2,······,k_m) \in K,x=(x_1,x_2,······,x_m) \in P,y=(y_1,y_2,······y_m) \in C\)

    定义:
    \[ 加密:e_k(x)=(x_1+k_1,x_2+k_2,···,x_m+k_m) \]

    \[ 解密:d_k(y)=(y_1-k_1,y_2-k_2,···,y_m-k_m) \]

    以上的运算均在\(Z_{26}\)上运行(模26)

实例

m=6,密钥字:cipher,明文:it is always a good time

对应的关系如下:

it is always a good time
ci ph erciph e rcip herc
# 维吉尼亚密码
# 加密
def Encrypt(key,plaintext,ascii):
    keylen=len(key)
    ptlen=len(plaintext)
    ciphertext =''
    i = 0
    while i < ptlen:
        j = i % keylen
        k = ascii.index(key[j])
        m = ascii.index(plaintext[i])
        ciphertext += ascii[(m+k)%26]
        i +=1
    return ciphertext

# 解密
def Decrypt(key,ciphertext,ascii):
    keylen=len(key)
    ctlen=len(ciphertext)
    plaintext =''
    i =0
    while i < ctlen:
        j = i % keylen
        k = ascii.index(key[j])
        m = ascii.index(ciphertext[i])
        if m < k:
            m +=26
            plaintext += ascii[m-k]
            i +=1
    return plaintext

if __name__ == '__main__':
    ascii='abcdefghijklmnopqrstuvwxyz'
    key=input().lower()
    
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!