密码学实验2 playfair密码的实现
作者:互联网
密码学实验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的问题等),但是凯撒本来也不支持大小写的,对伐
标签:playfair,tmp,text,密码,key,print,table,密码学 来源: https://blog.csdn.net/m0_49109277/article/details/116490846