其他分享
首页 > 其他分享> > 密码学实验2 playfair密码的实现

密码学实验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