文章目录

  • 一、题目
  • 二、古典密码
  • [1]. 移位密码
  • [2]. 仿射变换
  • 三、代码


一、题目

通过编程对古典密码进行解密:
1.使用穷尽密钥搜索法,破译如下利用移位密码加密的密文:
BEEAKFYDJXUQYHYJIQRYHTYJIQFBQDUYJIIKFUHCQD

2.设有仿射变换对一个明文加密得到的密文为:
EDSGICKXHUKLZVEQZVKXWKZUKCVUH 又已知明文的前两个字符是“IF”。对该密文解密。

二、古典密码

[1]. 移位密码

在进行移位密码时,有26种移位的方法,类似于凯撒加解密。
由于字母只有26个,所以密钥只能在[1,26]范围内
假设密钥为3、明文为A时,加密就是使A向右移动3位,密文为D
将密文D进行解密时,则需要使用密钥3向左移动3位,才能变回明文A

[2]. 仿射变换

进行仿射变换时,需要传入两个密钥a和b,字母也需要转换成数字,才能带入公式加密
字母转数字的规则:字母在字母表中的位置,且初始位置为0,即[A,Z][a,z][0,25] 加密公式:c = (a * m + b) mod 26 解密公式:m = ((a^-1)*(c-b)) mod 26

参数

介绍

a

密钥,a为整数,a与26互为素数,且范围在[0,25]

b

密钥,b为整数,且范围在[0,25]

c

密文,c为整数,且范围在[0,25]

m

明文,m为整数,且范围在[0,25]

a-1

a的逆元

mod

即求余运算%

在求解密钥a和b时,需要两个已知的密文c1、c2和两个对应的明文m1、m2
然后根据加密公式可以列出两个对应的方程式,联合求解
在编程中可以使用双循环,外循环a从0遍历到25,内循环b从0遍历到25
当a和b的值同时满足m1、m2加密后值为c1、c2时,就表明找到了密钥a、密钥b

a的逆元求解时,a和a的逆元满足公式:a-1 * a = 1 mod 26
例题求解9-1*(4-10)%26的值(相当于解密公式的**a=9、c=4、b=10**时,求解m) 解:
在计算时需要先求解9-1%26中的9-1,即求解一个值x,使( x9 )mod 26= 1即可。
通过一个个列举x的值,可以发现当x=3时,可以使式子( 3
9 )mod26=1
所以9的逆元为3
此时原式
= (3*(4-10))%26
= -18%26
= 8

三、代码

移位密码解密

密码学常见Python包 python密码学编程_密码学常见Python包

仿射变换解密

密码学常见Python包 python密码学编程_加密解密_02


密码学常见Python包 python密码学编程_加密解密_03


密码学常见Python包 python密码学编程_python_04

# coding=utf-8
# 作者:小狐狸
# 题目:古典密码
def menu():
    '''
    菜单界面
    '''
    print("-----------------------")
    print("|    0. 退出          |")
    print("|    1. 移位密码解密  |")
    print("|    2. 仿射变换解密  |")
    print("-----------------------")
##menu() #测试函数

def yiwei(string,number):
    '''
    将字符串的每个字母,向右移动指定的位数,并返回移动后的字符串
    如:A 向右移动3位,返回值为D
    string为字符串,number为整型
    A的ASCII码为65
    '''
    new_string = ""
    string = string.upper()  #转换为大写
    for i in string:        #移位操作
        #转换为ascii码后,经过移位变为新的ascii,再转换回字母
        new_string += chr((ord(i)-65+number)%26+65) 
    return new_string
##print(yiwei('AAA',3)) #测试函数正确性

def yiwei_decode(c):
    '''移位密码解密,并打印解密的结果'''
    for i in range(1,27): #穷尽密钥搜索,遍历范围[1,26]
        print(yiwei(c,i))
    print("解密结束")
##yiwei_decode("A") #测试函数正确性

def fangshe_key(m,c):
    '''
    通过已知的两对明文密文,求解得到两个密钥
    m为明文,c为密文
    [A-Z]转换为数字为[0-25]
    '''
    #大写
    m = m.upper()
    c = c.upper()
    #切片
    m1 = m[:1:]     #明文的第一个字母
    m2 = m[-1::]    #明文的最后一个字母
    c1 = c[:1:]     #密文的第一个字母
    c2 = c[-1::]    #密文的最后一个字母
##    print(m1,m2)
##    print(c1,c2)
    #转换为整数
    m1 = ord(m1)-65
    m2 = ord(m2)-65
    c1 = ord(c1)-65
    c2 = ord(c2)-65
##    print(m1,m2)
##    print(c1,c2)
    #穷举法
    for i in range(0,26):
        for j in range(0,26):
            if (m1*i+j)%26==c1 and (m2*i+j)%26==c2: #同时满足加密算法时
                return i,j
    return False
##print(fangshe_key("IF","ED")) #测试函数正确性

def fangshe_reverse(x,y):
    '''
    计算乘法逆元,求解x^-1(%y)的乘法逆元,并返回对应值
    '''
    i = 0
    while True:
        if x*i%26==1: #符合乘法逆元条件时
            return i
        i += 1
##print(fangshe_reverse(9,26)) #测试函数正确性

def fangshe_decode(c,a,b):
    '''
    仿射变换解密,并打印解密的结果
    c为密文,a和b为密钥
    0<=a,b<=25,且满足gcd(a,26)=1,a^-1表示a的逆元
    加密公式:c = a*m + b%26
    解密公式:m = (a^-1)*(c-b)%26
    '''
    new_string = ''
    c = c.upper() #大写转换
    for i in c: #逐个字母解密
        new_i = ord(i)-65 #转换成数字
        new_i = (fangshe_reverse(a,26)*(new_i - b))%26 #解密
        new_string += chr(new_i + 65) #转换回大写字母
    print(new_string)
    print("解密结束")
##fangshe_decode("ED",9,10) #测试函数正确性
    

if __name__=='__main__':
    while True:
        menu()
        choose = int(input("请选择: "))
        if choose==1:   
            string = input("请输入密文: ")
            yiwei_decode(string)
        elif choose==2:            
            string = input("请输入密文: ")
            m = input("已知明文:")
            c = input("对应密文:")
            a,b = fangshe_key(m,c)
            fangshe_decode(string,a,b)
        else:
            break