实验1 单表替代算法
1、 实验目的
- 了解替换密码的基本设计原理;
- 掌握基本的加密解密操作;
2、实验时间:2学时
3、实验内容:任选语言,实现课本例2-1,2-2。
4、实验过程及结果:
(1)例2-1
代码语言:javascript复制AlphaBet = ["A", "B", "C", "D", "E", "F", "G", "H", "I","J", "K", "L", "M", "N", "O", "P", "Q", "R","S", "T", "U", "V", "W", "X", "Y", "Z"]
alphaBet = ["a", "b", "c", "d", "e", "f", "g", "h", "i","j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
MiYao = ["q", "w", "e", "r", "t", "y", "u", "i", "o","p", "a", "s", "d", "f", "g", "h", "j", "k","l", "z", "x", "c", "v", "b", "n ", "m"]
mingwen = input("输入明文:")
miwen = ""
for i in mingwen:
if i.isspace() == True:
miwen = miwen ' '
continue
else:
if ord(i) <= ord("Z"):
miwen = miwen alphaBet[MiYao.index(i)]
elif ord(i) >= ord("a"):
miwen = miwen MiYao[alphaBet.index(i)]
print(miwen)
(2)例2-2
代码语言:javascript复制import string
def kaisa(s, k): #定义函数 接受一个字符串s 和 一个偏移量k
lower = string.ascii_lowercase #小写字母
upper = string.ascii_uppercase #大写字母
before = string.ascii_letters #无偏移的字母顺序 小写 大写
after = lower[k:] lower[:k] upper[k:] upper[:k]#偏移后的字母顺序 还是小写 大写
table = ''.maketrans(before, after) #创建映射表
return s.translate(table) #对s进行偏移 即加密
s = input()
for i in range(26):
print(kaisa(s, i))
5、心得体会:
怎么说呢,我的同学们都在用C,就我在拿python写这东西,这一部分我以前用python完成过,2-1是经典单表替代密码,2-2是经典的凯撒密码,这都是很经典的密码术,前人的智慧,在这次写脚本解决的时候,都可以用暴力解决。
2-1我本身是有一个输入秘钥进行替换的脚本,按照题目改成了以古典秘钥进行替换的脚本,凯撒加密的话,如果秘钥空间比较大的话,是不好用表替代的,最好还是用加减计算。但是这个题目只设计大小写字母,利用python代码的String库和字典切片可以简单创建大的字典。再通过映射阶。为了图省事,直接设置函数,在外面遍历直接进行爆破完成就行。
密码术的各种很奇妙,但是怎么说呢,在现代密码上基本不设防。
实验2 多表替代算法
1、 实验目的
- 了解替换密码的基本设计原理;
- 掌握基本的加密解密操作;
2、实验时间:2学时
3、实验内容:任选语言,实现课本例2-3,2-4。
4、实验过程及结果:
(1)例2-3仿射密码:
加密算法:
代码语言:javascript复制mingwen = input("输入明文:")
a=int(input("输入k0: "))
b=int(input("输入k1: "))
miwen = ""
for i in mingwen:
if i.isspace() == True:
miwen = miwen ' '
else:
miwen =miwen str(chr(((ord(i)-97)*a b)& 97))
print(miwen)
解密算法:
代码语言:javascript复制mingwen = ""
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
miwen = input("请输入解密字符:")
a = int(input("请输入a:"))
b = int(input("请输入b:"))
# 求a关于26的乘法逆元
x, y = get(a, 26)
a1 = x % 26
for i in miwen:
if i.isspace() == True:
mingwen = mingwen ' '
else:
mingwen=mingwen str(chr(a1 * (ord(i) - 97 - b) % 26 97))
print(mingwen)
(2)例2-4:
代码语言:javascript复制def add_list(x,y):
result = []
for i in range(len(x)):
z = x[i] y[i]
result.append(z)
return result
def c2n():
list_c = []
list_n = []
for i in range(26):
list_n.append(i)
list_c.append(chr(i 97))
dic_c2n = dict(map(lambda x,y:[x,y],list_c,list_n))
return dic_c2n
# 构造映射 num---->字符
def n2c():
list_c = []
list_n = []
for i in range(26):
list_n.append(i)
list_c.append(chr(i 97))
dic_n2c = dict(map(lambda x,y:[x,y],list_n,list_c))
return dic_n2c
# 实现列表元素对应相减(解密部分)
def sub_list(x,y):
result = []
for i in range(len(x)):
z = x[i] - y[i]
result.append(z)
return result
# 加密
def encode(s,key):
print('加密后的字符: ',end='')
dic_c2n = c2n()
dic_n2c = n2c()
list_s = []
list_key = []
list_finall = []
for i in s:
i = i.lower()
list_s.append(dic_c2n[i])
for i in key:
i = i.lower()
list_key.append(dic_c2n[i])
for i in list_key:
if len(list_key) <= len(list_s):
list_key.append(i)
list_result = add_list(list_s,list_key)
for i in list_result:
if i > 25:
i -= 26
list_finall.append(dic_n2c[i])
for i in list_finall:
print(i.upper(),end='')
# 解密
def decode(s,key):
print('解密后的字符: ',end='')
dic_c2n = c2n()
dic_n2c = n2c()
list_s = []
list_key = []
list_finall = []
for i in s:
i = i.lower()
list_s.append(dic_c2n[i])
for i in key:
i = i.lower()
list_key.append(dic_c2n[i])
for i in list_key:
if len(list_key) < len(list_s):
list_key.append(i)
list_result = sub_list(list_s,list_key)
for i in list_result:
if i < 0:
i = 26
list_finall.append(dic_n2c[i])
for i in list_finall:
print(i,end='')
# 函数入口
answer = input(f'请输入所需的操作:编码/E or 解码/D: ')
try:
if answer.upper() == 'E':
key = input('请输入Key:')
s = input('请输入需要加密的字符:')
encode(s,key)
elif answer.upper() == 'D':
key = input('请输入Key:')
s = input('请输入需要解密的字符:')
decode(s,key)
else:
print('输入错误!')
except KeyError:
print('请勿输入空格!')
5、心得体会:
怎么说呢,我的同学们都在用C,就我在拿python写这东西,这都是很经典的密码术,前人的智慧,在这次写脚本解决的时候,都可以用暴力解决。
虽然有点可惜,因为使用的python编程,我的本意是简单,其实这些程序的内容在我说了解的一个密码学库里有相应的内置函数,还是写了下,还是有些在意的问题,比如说我本身打算使用库函数技术函数的逆的,但是在实践中发现我记忆中用来求逆的函数无法处理非方阵的逆…….总之需要学的好多啊
实验3 周期置换密码与Playfair密码
1、 实验目的
(1)了解周期置换密码的基本设计原理;
(2)掌握基本的加密解密操作;
2、实验时间:2学时
3、实验内容:
(1)任选语言,实现课本例2-5。
(2)任选语言,实现课本例2-7。
4、实验过程及结果:
(1)例2-5Playfair密码
代码语言:javascript复制# Playfair密码
letter_list = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'
# 移除字符串中重复的字母
def remove_duplicates(key):
key = key.upper() # 转成大写字母组成的字符串
_key = ''
for ch in key:
if ch == 'J':
ch = 'I'
if ch in _key:
continue
else:
_key = ch
return _key
# 根据密钥建立密码表
def create_matrix(key):
key = remove_duplicates(key) # 移除密钥中的重复字母
key = key.replace(' ', '') # 去除密钥中的空格
for ch in letter_list: # 根据密钥获取新组合的字母表
if ch not in key:
key = ch
# 密码表
keys = [[i for j in range(5)] for i in range(5)]
for i in range(len(key)): # 将新的字母表里的字母逐个填入密码表中,组成5*5的矩阵
keys[i // 5][i % 5] = key[i] # j用来定位字母表的行
return keys
# 获取字符在密码表中的位置
def get_matrix_index(ch, keys):
for i in range(5):
for j in range(5):
if ch == keys[i][j]:
return i, j # i为行,j为列
def get_ctext(ch1, ch2, keys):
index1 = get_matrix_index(ch1, keys)
index2 = get_matrix_index(ch2, keys)
r1, c1, r2, c2 = index1[0], index1[1], index2[0], index2[1]
if r1 == r2:
ch1 = keys[r1][(c1 1) % 5]
ch2 = keys[r2][(c2 1) % 5]
elif c1 == c2:
ch1 = keys[(r1 1) % 5][c1]
ch2 = keys[(r2 1) % 5][c2]
else:
ch1 = keys[r1][c2]
ch2 = keys[r2][c1]
text = ''
text = ch1
text = ch2
return text
def get_ptext(ch1, ch2, keys):
index1 = get_matrix_index(ch1, keys)
index2 = get_matrix_index(ch2, keys)
r1, c1, r2, c2 = index1[0], index1[1], index2[0], index2[1]
if r1 == r2:
ch1 = keys[r1][(c1 - 1) % 5]
ch2 = keys[r2][(c2 - 1) % 5]
elif c1 == c2:
ch1 = keys[(r1 - 1) % 5][c1]
ch2 = keys[(r2 - 1) % 5][c2]
else:
ch1 = keys[r1][c2]
ch2 = keys[r2][c1]
text = ''
text = ch1
text = ch2
return text
def playfair_encode(plaintext, key):
plaintext = plaintext.replace(" ", "")
plaintext = plaintext.upper()
plaintext = plaintext.replace("J", "I")
plaintext = list(plaintext)
plaintext.append('#')
plaintext.append('#')
keys = create_matrix(key)
ciphertext = ''
i = 0
while plaintext[i] != '#':
if plaintext[i] == plaintext[i 1]:
plaintext.insert(i 1, 'X')
if plaintext[i 1] == '#':
plaintext[i 1] = 'X'
ciphertext = get_ctext(plaintext[i], plaintext[i 1], keys)
i = 2
return ciphertext
def playfair_decode(ciphertext, key):
keys = create_matrix(key)
i = 0
plaintext = ''
while i < len(ciphertext):
plaintext = get_ptext(ciphertext[i], ciphertext[i 1], keys)
i = 2
_plaintext = ''
_plaintext = plaintext[0]
for i in range(1, len(plaintext) - 1):
if plaintext[i] != 'X':
_plaintext = plaintext[i]
elif plaintext[i] == 'X':
if plaintext[i - 1] != plaintext[i 1]:
_plaintext = plaintext[i]
_plaintext = plaintext[-1]
_plaintext = _plaintext.lower()
return _plaintext
plaintext = input('明文:')
key = input('密钥:')
ciphertext = playfair_encode(plaintext, key)
print('加密后的密文:' ciphertext)
plaintext = playfair_decode(ciphertext, key)
print('解密后的明文:' plaintext)
(2)例2-7周期置换密码:
正常加密:
代码语言:javascript复制import numpy as np
miwen = ""
miyao=input('请输入秘钥顺序: ')
l1=len(miyao)
mingwen=input('请输入明文: ')
l2=len(mingwen)
for a in range(l2//l1-1,-1,-1):
for i in miyao:
miwen=miwen mingwen[(a-1)*6 int(i)-1]
print(miwen)
爆破解密:
代码语言:javascript复制import numpy as np
mingwen = ""
MY=int(input('请输入猜测的秘钥长度: '))
miwen=input('请输入秘文: ')
l2=len(miwen)
file=open("./秘钥排列.txt","w",encoding="utf-8")
lst=range(MY)
list=[str(i) for i in lst]
def permutations(position):
if position == len(list) - 1:
l="".join(list)
file.write("{}n".format(l))
else:
for index in range(position, len(list)):
list[index], list[position] = list[position], list[index]
permutations(position 1)
list[index], list[position] = list[position], list[index]
permutations(0)
file=open("./秘钥排列.txt","r")
while 1:
mingwen = ""
miyao = file.readline()
miyao=miyao.strip('n')
for a in range(l2 // MY - 1, -1, -1):
for i in miyao:
mingwen = mingwen miwen[(a-1)*6 int(i) - 1]
print(mingwen)
if not miyao:
break
file.close()
5、心得体会:
这周的两个题目难度都很大,Playfair密码的实验写了老久,在这里没有调用太多库函数,而周期性替换密码,这个正常的加密与解密都很正常。但是使用唯秘文攻击进行爆破,在猜测的秘钥长度下进行爆破,得到明文。