Python3實現Playfair密碼演算法加解密
阿新 • • 發佈:2020-10-13
題目一
金鑰矩陣的構造
新建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)
加密結果: