加密:
第一步:制表
密码表共5行5列,第一行(或第一列)是密钥,其余按照字母顺序。密钥中若有重复字母,则可将后面重复的字母去掉。同时i和j会被当作一个字母。
第二步:整理明文
将明文每两个字母组成一对。如果成对后有两个相同字母紧挨或最后一个字母是单个的,就插入一个字母X(或者Q)。
第三步:加密
首先将明文字母两两一组进行切分,并按照如下规则进行加密:
1)若两个字母不同行也不同列,则需要在矩阵中找到另外两个字母(第一个字母对应行优先)。使这四个字母成为一个长方形的四个角。
2)若两个字母同行,则取这两个字母右方的字母(若字母在最右方则取最左方的字母)。
3)若两个字母同列,则取这两个字母下方的字母(若字母在最下方则取最上方的字母)。
解密
第一步同加密的第一步。
第二步:解密
首先将密文字母两两一组进行切分,并按照如下规则进行加密:
1)若两个字母不同行也不同列,则需要在矩阵中找到另外两个字母(第一个字母对应行优先)。使这四个字母成为一个长方形的四个角。
2)若两个字母同行,则取这两个字母左方的字母(若字母在最左方则取最右方的字母)。
3)若两个字母同列,则取这两个字母上方的字母(若字母在最上方则取最下方的字母)。
解密脚本:
#制表(采用横向制表)
def chess_map(k):
map_k = ''
alp = 'abcdefghiklmnopqrstuvwxyz' #i j视为同一个字母,j去除
for i in k:
if i not in map_k:
map_k += i
for i in alp:
if i not in map_k:
map_k += i
s = []
for i in range(0,len(map_k),5):
s.append(map_k[i:i+5])
return s
#解密
def playfair_decode(c,k):
temp = ''
for i in k:
for j in i:
temp += j
dex = ''
for i in c:
x = temp.index(i)//5
y = temp.index(i)%5
dex += str(x)+ str(y)
m = ''
for i in range(0,len(dex),4):
if dex[i] ==dex[i+2]:#同行
m += k[int(dex[i])][(int(dex[i+1])-1)%5]+k[int(dex[i+2])][(int(dex[i+3])-1)%5]
#以第一个字母对应的明文优先
elif dex[i+1] == dex[i+3]:#同列
m += k[(int(dex[i])-1)%5][int(dex[i+1])]+k[(int(dex[i+2])-1)%5][int(dex[i+3])]
#以第一个字母对应的明文优先
else:
m += k[int(dex[i])][int(dex[i+3])]+k[int(dex[i+2])][int(dex[i+1])]
#以第一个字母对应的行优先
#出现两个字母相同的,即同行同列的怎么办???
return m
key = chess_map('playfair'.lower())#密钥
c = 'lswpigtqtklbsZ'.lower()#密文
print(playfair_decode(c,key))