Python Playfair

Playfair.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#########################Playfair密码#########################

#约定1:若明文字母数量为奇数,在明文末尾添加一个'Z'
#约定2:'I'作为'J'来处理

#字母表
letter_list='ABCDEFGHJKLMNOPQRSTUVWXYZ'

#密码表
T_letter=['','','','','']
#根据密钥建立密码表
def Create_Matrix(key):
key=Remove_Duplicates(key) #移除密钥中的重复字母
key=key.replace(' ','') #去除密钥中的空格
for ch in letter_list: #根据密钥获取新组合的字母表
if ch not in key:
key+=ch

j=0
for i in range(len(key)): #将新的字母表里的字母逐个填入密码表中,组成5*5的矩阵
T_letter[j]+=key[i] #j用来定位字母表的行
if 0==(i+1)%5:
j+=1

#移除字符串中重复的字母
def Remove_Duplicates(key):
key=key.upper() #转成大写字母组成的字符串
_key=''
for ch in key:
if ch=='I':
ch='J'
if ch in _key:
continue
else:
_key+=ch
return _key

#获取字符在密码表中的位置
def Get_MatrixIndex(ch):
for i in range(len(T_letter)):
for j in range(len(T_letter)):
if ch==T_letter[i][j]:
return i,j #i为行,j为列

#加密
def Encrypt(plaintext,T_letter):
ciphertext=''

if len(plaintext) % 2 !=0: #如果新的明文长度为奇数,在其末尾添上'Z'
plaintext+='Z'

i=0
while i<len(plaintext): #对明文进行遍历
if True==plaintext[i].isalpha(): #如果是明文是字母的话,
j=i+1 #则开始对该字母之后的明文进行遍历,
while j<len(plaintext): #直到遍历到字母,进行加密
if True==plaintext[j].isalpha():
if 'I'==plaintext[i].upper(): #
x=Get_MatrixIndex('J') #
else: #
x=Get_MatrixIndex(plaintext[i].upper()) #对字符在密码表中的坐标
if 'I'==plaintext[j].upper(): #进行定位,同时将'I'作为
y=Get_MatrixIndex('J') #'J'来处理
else: #
y=Get_MatrixIndex(plaintext[j].upper()) #

if x[0]==y[0]: #如果在同一行
ciphertext+=T_letter[x[0]][(x[1]+1)%5]+T_letter[y[0]][(y[1]+1)%5]
elif x[1]==y[1]: #如果在同一列
ciphertext+=T_letter[(x[1]+1)%5][x[0]]+T_letter[(y[1]+1)%5][y[0]]
else: #如果不同行不同列
ciphertext+=T_letter[x[0]][y[1]]+T_letter[y[0]][x[1]]
break; #每组明文对加密完成后,结束本次对明文的遍历
j+=1
i=j+1 #每次对明文的遍历是从加密过后的明文的后一个明文开始的,结束本次循环
continue
else:
ciphertext+=plaintext[i] #如果明文不是字母,直接加到密文上
i+=1

return ciphertext

#解密
def Decrypt(ciphertext,T_letter):
plaintext=''
if len(ciphertext) % 2 !=0: #如果新的密文长度为奇数,在其末尾添上'Z'
ciphertext+='Z'

i=0
while i<len(ciphertext): #对密文进行遍历
if True==ciphertext[i].isalpha(): #如果是密文是字母的话,
j=i+1 #则开始对该字母之后的密文进行遍历,
while j<len(ciphertext): #直到遍历到字母,进行解密
if True==ciphertext[j].isalpha():
if 'I'==ciphertext[i].upper(): #
x=Get_MatrixIndex('J') #
else: #
x=Get_MatrixIndex(ciphertext[i].upper()) #对字符在密码表中的坐标
if 'I'==ciphertext[j].upper(): #进行定位,同时将'I'作为
y=Get_MatrixIndex('J') #'J'来处理
else: #
y=Get_MatrixIndex(ciphertext[j].upper()) #

if x[0]==y[0]: #如果在同一行
plaintext+=T_letter[x[0]][(x[1]-1)%5]+T_letter[y[0]][(y[1]-1)%5]
elif x[1]==y[1]: #如果在同一列
plaintext+=T_letter[(x[1]-1)%5][x[0]]+T_letter[(y[1]-1)%5][y[0]]
else: #如果不同行不同列
plaintext+=T_letter[x[0]][y[1]]+T_letter[y[0]][x[1]]
break; #每组密文对解密完成后,结束本次对密文的遍历
j+=1
i=j+1 #每次对密文的遍历是从解密过后的密文的后一个密文开始的,结束本次循环
continue
else:
plaintext+=ciphertext[i] #如果密文不是字母,直接加到明文上
i+=1
return plaintext



#主函数

if __name__=='__main__':

print("加密请按D,解密请按E:")
user_input=input();
while(user_input!='D' and user_input!='E'):#输入合法性检测
print("输入有误!请重新输入:")
user_input=input()

print('请输入密钥,密钥由英文字母组成:')
key=input()
Create_Matrix(key) #建立密码表
if user_input=='D': #加密
print('请输入明文:')
plaintext=input()
print("密文为:\n%s" % Encrypt(plaintext,T_letter))

else: #解密

print('请输入密文:')
ciphertext=input()
print('明文为:\n%s' % Decrypt(ciphertext,T_letter))

评论