发布于2022年10月15日3年前 密码学实验2 playfair密码的实现 这不是有手就行,一些刁钻的细节还没有研究,这里先只实现一般的加解密 开始之前,我想说,有网站不香么playfair在线加解密. 结束 一、准备工作 首先playfair,第一次遇到在水古典密码的时候(加解密原理下面也有,具体的细节建议百度),与一般的多表加密和单表加密不同的是,它好像不能被词频,然后用类似多表替代的破解方案去的话,好像也不行,因为没有密钥填充的过程,嘎嘎嘎嘎 果然I和J也是一个攻击点 好了,言归正传 首先准备了两个函数,用来转换字母表和找到行列坐标 def tableau_used(table): # 注意二维数组的初始化方式 lists = [[' ' for _ in range(5)] for _ in range(5)] for i in range(len(table)): lists[i//5][i % 5] = table[i] return lists def find_xy(target, lists): for i in range(5): for j in range(5): if lists[i][j] == target: return i, j 二、加密 大致的流程可参考度娘 遇到的一些问题,比如numpy库的二维数组里str和别的一般的str类型不同,可能会出错,还有从网上抄来的正则表达式的库re的使用,将字符串拆分成两个,其他都没什么吧 def playfair_encode(plaintext, table): lists = tableau_used(table) # 密文处理,多出来或者重复的加X tmp_text = plaintext for i in ascii_uppercase: if i * 2 in tmp_text: tmp_text = tmp_text.replace(i+i, i+'X'+i) if len(tmp_text) % 2: tmp_text += 'X' tmp_text = re.sub(r"(?<=\w)(?=(?:\w\w)+$)", " ", tmp_text).split() ciphertext = '' # 加密三步走 for ii in tmp_text: x1 = find_xy(ii[0], lists)[0] y1 = find_xy(ii[0], lists)[1] x2 = find_xy(ii[1], lists)[0] y2 = find_xy(ii[1], lists)[1] tmp_item = '' # 同一行 if y1 == y2: tmp_item = lists[(x1+1) % 5][y1] + lists[(x2+1) % 5][y2] # 同一列 elif x1 == x2: tmp_item = lists[x1][(y1 + 1) % 5] + lists[x2][(y2 + 1) % 5] # 矩形,规定横向替换 else: tmp_item = lists[x1][y2] + lists[x2][y1] ciphertext += tmp_item return ciphertext 三、解密 解密也主要参考度娘 但其实就想必加密而言,改一下符号就好,而且没有加密繁琐 def playfair_decode(ciphertext, table): lists = tableau_used(table) tmp_text = ciphertext tmp_text = re.sub(r"(?<=\w)(?=(?:\w\w)+$)", " ", tmp_text).split() ciphertext = '' # 加密三步走 for ii in tmp_text: x1 = find_xy(ii[0], lists)[0] y1 = find_xy(ii[0], lists)[1] x2 = find_xy(ii[1], lists)[0] y2 = find_xy(ii[1], lists)[1] tmp_item = '' # 同一行 if y1 == y2: tmp_item = lists[(x1 - 1) % 5][y1] + lists[(x2 - 1) % 5][y2] # 同一列 elif x1 == x2: tmp_item = lists[x1][(y1 - 1) % 5] + lists[x2][(y2 - 1) % 5] # 矩形,规定横向替换 else: tmp_item = lists[x1][y2] + lists[x2][y1] ciphertext += tmp_item return ciphertext 四、测试 字母表的生成放在测试这部分了 # 构造加密解密使用的字母表 table = key for i in alphabet: if i in table: continue table += i assert len(table) == 25 j = 0 print("得到的字母表如下:") for i in table: j += 1 if i == 'I': print("I(J)", end='') else: print(i, end='\t') if j >= 5: print() j = 0 这里我是规定用有J的地方用I来代替 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/4/23 14:31 # @Author : Will # @File : t3xt.py # @Software: PyCharm from sage import playfair_decode, playfair_encode, tableau_used from string import ascii_uppercase import sys # 将I和J视为同一个字母,这里把出现J的地方都当成I alphabet = ascii_uppercase.replace('J', '') print("请输入密钥:", end='') tmp_key = input().upper() tmp_key = tmp_key.replace('J', 'I') # 去重去空格 tmp_key = "".join(tmp_key.split()) key = '' for i in tmp_key: if i in key: continue key += i print(key) # 构造加密解密使用的字母表 table = key for i in alphabet: if i in table: continue table += i assert len(table) == 25 j = 0 print("得到的字母表如下:") for i in table: j += 1 if i == 'I': print("I(J)", end='') else: print(i, end='\t') if j >= 5: print() j = 0 print('*****************') print("* 1.加密 *") print("* 2.解密 *") print("* 3.退出 *") print('*****************') print("请输入你的选择:", end='') tip = input() while 1: if tip == '1': print("请输入你要加密的明文:") plaintext = (''.join(input().split())).upper().replace('J', 'I') # 加密 ciphertext = playfair_encode(plaintext, table) print("加密的结果是:{0}".format(ciphertext.upper())) break elif tip == '2': print("请输入你要解密的密文:") ciphertext = input().upper() # 解密 plaintext = playfair_decode(ciphertext, table) if 'XX' in plaintext: print("WOW, you are so lucky! There are XX in your text.") continue if len(ciphertext) % 2 != 0: print("WOW, you make me very confused") continue print("解密的结果是:{0}".format(plaintext.lower())) break elif tip == '3': print("师傅再见") break else: print("我不想讨论这些问题") continue 上面两个函数我单独拎出来,打算自己实现一个sage常见的加解密库 五、运行结果 应该是对的 最后当然至于一些细节,能实现最好了(比如特殊字符的直接保留,还有结果报不保留原来的空格还有一些处理不了的特殊情况,I和J的问题等),但是凯撒本来也不支持大小写的,对伐
创建帐户或登录后发表意见