仿射密码实验——Python实现(完整解析版)
文章目录
- 前言
- 实验内容
- 实验操作步骤
- 1.编写主程序
- 2.编写加密模块
- 3.编写解密模块
- 4.编写文件加解密模块
- 实验结果
- 实验心得
- 实验源码
- scirpt.py
- usefile.py
前言
实验目的
1)初步了解古典密码
2)掌握仿射密码的实现
实验方法
根据下图仿射密码(变换)加解密的描述,用所熟悉的语言,完成实验内容、描述实验操作步骤、实验结果与实验心得。
实验环境
计算机语言:Python
开发环境:Pycharm
原理
实验内容
- 编程实现仿射密码,要求有加密步骤和解密步骤。若输入参数a,b不合法,则报错。
- 提供两种解密方法,一是掌握密钥破解,而是无密钥的暴力破解
- 使用两种加解密的操作,一是命令行的输入输出,而是文件的读取写入生成
- 加解密过程中应考虑大小写
实验操作步骤
1.编写主程序
在main主程序里,需要有相应的功能提示
作为菜单栏使用
不同的数字对应实现不同的功能:1加密2解密3文件形式加解密4退出程序
2.编写加密模块
需求有:提示输入明文和密钥,对明文进行仿射密码方式的加密,最后输出
m接收用户输入的明文
c作为数组来存储,a和b就是密钥需要用户提供
对于输入的a和b需整形化,然后判断a、b是否互素通过ab的最大公因数是否为1判断
若不互素则提示用户重新输入
达成互素条件后
首先采用正则表达式处理一下用户输入一些特殊符号
(如果不处理的话,那么形成的密文最后也是解密不了的)
接着采用replace去除空格
进入encrypt模块
在这个模块中,原理就是将之前用户输入的参数m,a,b传入
然后通过先转化成ascii码和进行模运算,这里计算得到的ascii码chr后,得到的是大写的英文字母,为此最后输出的时候提供给用户两种结果:大写和小写
3.编写解密模块
首先提示输入密文,考虑之前我们加密后的结果一般都是只有英文字母的组合
这里我就只有进行大小写的处理
提示用户是否知道密钥,若有则接受参数a和b,同样得判断a,b是否互素来确认密钥的合法性
然后由a计算出k,再传入decrypt模块解密
解密其实就是加密数学上的逆运算
这里刚刚好相反,通过一系列计算得到的是一串小写英文字母
那与之前一样,我们需要给用户提供大写和小写的结果
假如选择不知道密钥的话,那么就是采用暴力破解
也就是数字组合一个个试,这里通过对仿射原理的理解便可以缩小点范围
定义的la数组和lb数组分别如图
4.编写文件加解密模块
这个文件我命名为usefile.py,并且作为库来给之前的脚本代码引用
这个文件其实和之前的代码以及实现的功能差不多
不过为了代码看起来不那么冗长,就单独再写一个模块了
以下是该代码的展示
密钥的输入
互素条件的判断
逆元的求解
文件加密
文件解密
主函数模块
实验结果
开始使用程序
运行script.py
输入数字1
我们用hello作为例子,密钥就为3和4吧
得到密文为ZQLLU 或 zqllu
这次试一下特殊符号
输入hell,,!!o
可以看到加密结果与之前一致
那我们现在试着解密
输入之前的密文zqllu,先按照有密钥解密
得到hello说明正确
再试一下无密钥暴力破解
这一次故意输入大写的ZQLLU,然后寻找一下正确的明文
Ok,与我们之前有密钥解出来结果一致,说明代码可行
好的,我们来看看文件模块运行如何
出现usefile里特有的菜单模块
事先我创建了一个test.txt,里面内含明文hello
运行功能1看看
然后当前目录下多了ciphertext.txt文件,查看该文件
结果没错
我们再试解密功能
该目录下多出plaintext.txt文件,查看该文件
还原成功,是明文hello
这里是提供了密钥,如果暴力破解就是和之前script文件中一致
实验心得
作为古典密码的一种,仿射密码的原理其实挺简单的,所以这次使用python来实现关于仿射密码的加解密难度不大,中间遇到的一些问题还是让我收获不少:加解密时要注意英文字母大小写、特殊符号需要处理、chr和ord的配合使用、编写不同的函数模块和文件来实现CLI版的功能等等,让我对于python的使用更加的得心应手。
很喜欢python的话语:人生苦短,我用python。
希望之后继续使用python解决有关密码学的问题。
实验源码
scirpt.py
# 暴力破解
import usefile as u
import re
la = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
lb = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
# 最大公约数
def gcd(a, b):
while b != 0:
tem = a % b
a = b
b = tem
return a
# 加密
def encrypt(m, c, a, b):
for i in range(len(m)):
# 加密成相应的大写字母
c.append(chr(((ord(m[i]) - 97) * a + b) % 26 + 65))
d = ''.join(c)
print(d,"或 {}".format(d.lower()))
# 求逆元
def niyuan(a, b):
ny = 1
while (a * ny) % b != 1:
ny += 1
return ny
# 解密
def decrypt(c, k, b):
mw = []
for i in range(len(c)):
tem = ord(c[i]) - 65 - b
if tem < 0:
tem += 26
mw.append(chr((k * tem) % 26 + 97))
print("k=" + str(k) + ", b=" + str(b) + "时,解密后的明文为:")
res = ''.join(mw)
print(res,"或 {}".format(res.upper()))
def jiami():
m = input("请输入明文:")
c = []
x, y = input("请输入a和b: ").split()
a = int(x)
b = int(y)
while gcd(a, b) != 1:
x, y = input("a和b不互素,请重新输入a和b: ").split()
a = int(x)
b = int(y)
print("明文内容为:")
print(m)
r = "[!!+-=——,,。??、]"
m = re.sub(r, ' ', m)
m = m.replace(' ', '')
print("加密后的密文为:")
encrypt(m, c, a, b)
def jiemi():
m = input("请输入密文:")
c = []
q = input("是否有密钥,有请输入1,无则输入0:")
print("密文内容为:")
print(m)
if int(q)==1:
x, y = input("请输入a和b: ").split()
a = int(x)
b = int(y)
while gcd(a, b) != 1:
x, y = input("a和b不互素,请重新输入a和b: ").split()
a = int(x)
b = int(y)
m = m.upper()
for i in range(len(m)):
# 加密成相应的大写字母
c.append(m[i])
print("知道密钥破解:")
k = niyuan(a, 26)
decrypt(c, k, b)
elif int(q)==0:
m = m.upper()
# 加密成相应的大写字母
for i in range(len(m)):
c.append(chr(ord(m[i])))
print("不知道秘钥破解,暴力破解如下: ")
for i in range(0, 12):
for j in range(0, 26):
decrypt(c, la[i], lb[j])
#实现
if __name__ == "__main__":
# 明文
while True:
print("-------------------------")
print("1.仿射密码加密")
print("2.仿射密码解密")
print("3.文件仿射加解密")
print("4.程序退出")
n = input("请输入功能对应的数字:")
print("-------------------------")
if int(n)==1:
jiami()
elif int(n)==2:
jiemi()
elif int(n)==3:
u.main()
elif int(n)==4:
print("感谢使用!")
break
else:
print("输入有误,请重新输入!")
usefile.py
#仿射密码加密与解密实现算法
# -*- coding=utf-8 -*-
#输入密钥
def accept():
k1,k2 = map(int,input('请输入两个密钥(以空格隔开):').split())
while gcd(k1, 26) !=1:
k1,k2 = map(int,input('k1和26不互素,请重新输入密钥:').split())
return k1,k2
#判断互素
def gcd(k1,m):
t = 0
while m!=0:
t = m
m = k1%m
k1 = t
return k1
#求逆元
def niyuan(k1):
n = 1
while (k1 * n) % 26 != 1:
n += 1
return n
#加密算法
def encrypt():
#输入密钥
k1,k2 = accept()
n = input("请输入当前目录下需要加密文件名:")
f = open(n)
plain = f.read()
#print(plain)
c = []
for i in range(len(plain)):
#小写字母
if plain[i].islower():
c.append(chr(((ord(plain[i])-97)*k1+k2)%26+97))
#大写字母
elif plain[i].isupper():
c.append(chr(((ord(plain[i])-65)*k1+k2)%26+65))
#其他
else :
c.append(plain[i])
cipher = ''.join(c)
w = open('ciphertext.txt','w')
w.write(cipher)
print('加密完成!')
f.close()
w.close()
#解密算法
def decrypt():
#输入密钥
k1,k2 = accept()
#逆元
ny = niyuan(k1)
str = input("请输入当前目录下需要解密文件名:")
f = open(str)
cipher = f.read()
p = []
for i in range(len(cipher)):
#小写字母
if cipher[i].islower():
t1 = ord(cipher[i])-97-k2
if t1 < 0:
t1 +=26
p.append(chr((ny * t1)%26+97))
#大写字母
elif cipher[i].isupper():
t2 = ord(cipher[i])-65-k2
if t2 < 0:
t2 +=26
p.append(chr((ny * t2)%26+65))
#其他
else :
p.append(cipher[i])
plain = ''.join(p)
w = open('plaintext.txt','w')
w.write(plain)
print('解密完成!')
f.close()
w.close()
def main():
while True:
print("--------文件加解密操作--------")
print("加密【1】:")
print("解密【2】:")
print("退出【3】:")
ch = int(input("请输入对应功能数字:"))
if ch == 1:
encrypt()
elif ch == 2:
decrypt()
elif ch == 3:
print("感谢使用!")
exit()
else:
print("请输入1或2")