# playfair
# 基本原理
Playfair 算法基于一个 5*5 的字母矩阵,该矩阵使用一个关键词构造,方法是按从左到右、从上到下顺序,填入关键词的字母 (去除重复字母) 后,将字母表其作余字母填入。
例如:关键词取:monarchy 时,字母矩阵为下图如示 (矩阵只能放 25 个字母,I 与 J 同)
# 加密规则
Playfair 加密算法是先将明文按两个字母一组进行分组,然后在矩阵中找对应的密文。
取密文的规则如下:
1. 若明文出现相同字母在一组,则在重复的明文字母中插入一个填充字母 (eg:z) 进行分隔后重新分组 (eg: balloon 被重新分组为 ba lz lo on)
2. 若分组到最后一组时只有一个字母,则补充字母 z
3. 若明文字母在矩阵中同行,则循环取其右边下一个字母为密文 (矩阵最右边的下一个是最左边的第一个)(eg: ar 被加密为 RM)
4. 若明文字母在矩阵中同列,则循环取其下边下一个字母为密文 (矩阵最下边的下一个是最上边的第一个)(eg: mu 被加密为 CM)
5. 若明文字母在矩阵中不同行不同列,则取其同行且与同组另一字母同列的字母为密文 (eg: hs 被加密为 BP,ea 被加密为 IM 或 JM)
- 举例:
明文为 we are discovered save yourself,分组成为 we ar ed is co ve re ds av ey ou rs el fz;
用上述矩阵加密后的密文为:UG RM KC SX HM UF MK BT OX GC MV AT LU KV
下面为代码 解密之后还没解决一些问题
import string | |
#j 用 i 代替 | |
table="abcdefghiklmnopqrstuvwxyz" | |
def get_key(key): | |
key=key.lower() | |
k=[] | |
c=[] | |
j=0 | |
k1=[] | |
for i in key: | |
if(i not in k1): | |
if(i=='j'): | |
i='i' | |
c.append(i) | |
k1.append(i) | |
j+=1 | |
if(j==5): | |
j=0 | |
k.append(c) | |
c=[] | |
for i in table: | |
if(i not in k1): | |
c.append(i) | |
k1.append(i) | |
j += 1 | |
if (j == 5): | |
j = 0 | |
k.append(c) | |
c = [] | |
return k | |
def get_position(m,key): | |
for i in range(5): | |
for j in range(5): | |
if(m==key[i][j]): | |
return i,j | |
def encrypt(m,key): | |
m1='' | |
l=len(m) | |
i=0 | |
#两两分组相同字母不能在同一组 | |
while(i<len(m)-1): | |
if(m[i]==m[i+1]): | |
m1=m1+m[i]+'z' | |
i=i+1 | |
l+=1 | |
else: | |
m1=m1+m[i]+m[i+1] | |
i+=2 | |
#两两分组如果长度为奇数则末尾加 z | |
if(l%2==1): | |
m1=m1+m[len(m)-1]+'z' | |
print(m1) | |
c='' | |
for i in range(0,l,2): | |
i1,j1=get_position(m1[i],key) | |
i2,j2=get_position(m1[i+1],key) | |
#在同一行 | |
if(i1==i2): | |
c=c+key[i1][(j1+1)%5]+key[i1][(j2+1)%5] | |
#在同一列 | |
elif(j1==j2): | |
c=c+key[(i1+1)%5][j1]+key[(i2+1)%5][j2] | |
else: | |
c=c+key[i1][j2]+key[i2][j1] | |
return c | |
def decrypt(c,key): | |
m = '' | |
for i in range(0, len(c), 2): | |
i1, j1 = get_position(c[i], key) | |
i2, j2 = get_position(c[i + 1], key) | |
# 在同一行 | |
if (i1 == i2): | |
m = m + key[i1][(j1 - 1) % 5] + key[i1][(j2 - 1) % 5] | |
# 在同一列 | |
elif (j1 == j2): | |
m = m + key[(i1 - 1) % 5][j1] + key[(i2 - 1) % 5][j2] | |
else: | |
m = m + key[i1][j2] + key[i2][j1] | |
#如果最后一位是 z 则去掉 | |
if(m[len(m)-1]=='z'): | |
m=m[:-1] | |
return m | |
key=input("输入密钥: ") | |
key=get_key(key) | |
message=input("输入明文: ") | |
message=message.replace('j','i').replace(' ','') | |
cipher=encrypt(message,key) | |
print(cipher) | |
message=decrypt(cipher,key) | |
print(message) |