1. 程式人生 > 實用技巧 >Python3實現Playfair密碼演算法加解密

Python3實現Playfair密碼演算法加解密

題目一

金鑰矩陣的構造

新建5x5的表格,依次填入金鑰單詞,字母不重複,然後字母a-z一次不重複填入,注意字母i和字母j佔據同一個位置,一般來說加密的時候明文中的j字母都可以替換成字母i。

密文兩兩分組

密文:

KXJEY   UREBE   ZWEHE   WRYTU   HEYFS
KREHE   GOYFI   WTTTU   OLKSY   CAJPO
BOTEI   ZONTX   BYBWT   GONEY   CUZWR
GDSON   SXBOU   YWRHE   BAAHY   USEDQ

值得注意的是,這裡每一個分組的兩字母是不重複的(加密過程會注意這一點,不過本題目只是解密)。
取小寫、替換j為i、兩兩分組的指令碼:

ciper = 
"KXJEYUREBEZWEHEWRYTUHEYFSKREHEGOYFIWTTTUOLKSYCAJPOBOTEIZONTXBYBWTGONEYCUZWRGDSONSXBOUYWRHEBAAHYUSEDQ"
ciper = ciper.lower()
ciper = ciper.replace('j','i')
cl = [ciper[i:i+2] for i in range(len(ciper)) if i%2 == 0]

結果:

解題過程

使用指令碼書寫針對‘royal new zealand navy’金鑰系統的playfair解密演算法:

# 尋找二維列表中指定元素的索引座標,不存在返回None
# 可擴充套件到numpy.array或numpy.matrix等二位陣列、矩陣型別
def find_element(matrix, value):
	for row in range(len(matrix)):
		if value in matrix[row]:
			return (row, matrix[row].index(value))
	return None
# 解密金鑰矩陣
DecodeKeyMatrix = [
	['r', 'o', 'y', 'a', 'l'], 
	['n', 'e', 'w', 'z', 'd'], 
	['v', 'b', 'c', 'f', 'g'], 
	['h', 'i', 'k', 'm', 'p'], # i/j代表同一個元素
	['q', 's', 't', 'u', 'x']
]

def decode(twoletter_ciper):
	global DecodeKeyMatrix
	(_1r, _1c) = find_element(DecodeKeyMatrix, twoletter_ciper[0])
	(_2r, _2c) = find_element(DecodeKeyMatrix, twoletter_ciper[1])
	if _1r == _2r:
		return DecodeKeyMatrix[_1r][_1c - 1] + DecodeKeyMatrix[_2r][_2c - 1]
	elif _1c == _2c:
		return DecodeKeyMatrix[_1r - 1][_1c] + DecodeKeyMatrix[_2r - 1][_2c]
	else:
		return DecodeKeyMatrix[_1r][_2c] + DecodeKeyMatrix[_2r][_1c]

執行主函式:

if __name__ == '__main__':
	plaintext = ""
	ciper = "KXJEYUREBEZWEHEWRYTUHEYFSKREHEGOYFIWTTTUOLKSYCAJPOBOTEIZONTXBYBWTGONEYCUZWRGDSONSXBOUYWRHEBAAHYUSEDQ"
	ciper = ciper.lower()
	ciper = ciper.replace('j','i')
	cl = [ciper[i:i+2] for i in range(len(ciper)) if i%2 == 0]
	for twoletter in cl:
		plaintext += decode(twoletter)
	print(plaintext)

執行結果:

去除佔位符X,得到明文:pt boat one owe nine lost in action in blackess strait two miles sw meresu coce crew of twelve request any information

題目二

本題是playfair密碼演算法的加密過程

使用金鑰矩陣:

#加密金鑰矩陣
#會比解密矩陣多最後一行(對應第一行)、最後一列(對應第一列)的冗餘
EncodeKeyMatrix = [
	['m','f','h','i','k','m'],
	['u','n','o','p','q','u'],
	['z','v','w','x','y','z'],
	['e','l','a','r','g','e'], 
	['d','s','t','b','c','d'],
	['m','f','h','i','k',None]
 ]

加密演算法:

def encode(twoletter_text):
	global EncodeKeyMatrix2
	(_1r, _1c) = find_element(EncodeKeyMatrix2, twoletter_text[0])
	(_2r, _2c) = find_element(EncodeKeyMatrix2, twoletter_text[1])
	if _1r == _2r:
		return EncodeKeyMatrix2[_1r][_1c + 1] + EncodeKeyMatrix2[_2r][_2c + 1]
	elif _1c == _2c:
		return EncodeKeyMatrix2[_1r + 1][_1c] + EncodeKeyMatrix2[_2r + 1][_2c]
	else:
		return EncodeKeyMatrix2[_1r][_2c] + EncodeKeyMatrix2[_2r][_1c]

還有些一個初始化函式init(),來處理明文:取小寫、去除特殊標點符號、末尾補齊(使明文長度為偶數)、兩兩分組;最後一個任務是關鍵點,分組字母不能相同,若是則要在中間差值字母'x'或'q':

def detect(s):
	if len(s) == 2 and s[0] == s[1]:
		temp = 'x' if s[0] != 'x' else 'q'
		return s[0] + temp + s[0]
	else:
		return s

def init(info):
	info = info.lower()
	info = re.sub(" |\.|,", "", info)
	while True:
		flag = 0
		info_li = [info[i:i+2] for i in range(len(info)) if i%2 == 0]
		_li = map(detect, info_li)
		for word in _li:
			if len(set(word)) == 3:
				flag = 1
				break
		info = ''.join(_li)
		if not flag:
			break
	info += 'x' if len(info)%2==1 else ''
	if info[-2] == 'x':
		info[-1] == 'q'
	return info

可以看一下效果:

現在給see單詞中多新增一個字母s變成ssee,檢視效果:

主函式程式碼:

ciper = ""
message = "Must see you over Cadogan West.Coming at once."
message = init(message)
mess_li = [message[i:i+2] for i in range(len(message)) if i%2 == 0]

for twoletter in mess_li:
	ciper += encode(twoletter)
print(ciper)

加密結果: