簡述
創(chuàng)新互聯(lián)于2013年開始,公司以成都做網(wǎng)站、成都網(wǎng)站制作、系統(tǒng)開發(fā)、網(wǎng)絡推廣、文化傳媒、企業(yè)宣傳、平面廣告設計等為主要業(yè)務,適用行業(yè)近百種。服務企業(yè)客戶千余家,涉及國內(nèi)多個省份客戶。擁有多年網(wǎng)站建設開發(fā)經(jīng)驗。為企業(yè)提供專業(yè)的網(wǎng)站建設、創(chuàng)意設計、宣傳推廣等服務。 通過專業(yè)的設計、獨特的風格,為不同客戶提供各種風格的特色服務。希爾密碼是利用矩陣進行加密的一種加密算法,其本質(zhì)是一種多表代換密碼。
百科:
希爾密碼是運用基本矩陣論原理的替換密碼,由Lester S. Hill在1929年發(fā)明。
每個字母當作26進制數(shù)字:A=0, B=1, C=2… 一串字母當成n維向量,跟一個n×n的矩陣相乘,再將得出的結(jié)果模26。
注意用作加密的矩陣(即密匙)在 必須是可逆的,否則就不可能解碼。只有矩陣的行列式和26互質(zhì),才是可逆的。
希爾密碼由于采用矩陣運算加密,因此在相同的明文加密時,可能會出現(xiàn)不同的密文,因此可以很好的抵御字母頻率攻擊法。
加解密
加密:
1、定義一個矩陣a(須存在逆矩陣)作為加密密鑰:
[1,2,1]
[0,2,1]
[1,0,2]
2、將需要加密的明文字母轉(zhuǎn)換為其對應的字母表數(shù)字(1-a,2-b……);
3、將轉(zhuǎn)換后的明文數(shù)字序列按照密鑰矩陣的階數(shù)進行分組(如本次為3個字符一組);
4、每組數(shù)字序列和密鑰矩陣進行矩陣的乘法運算(1x3 矩陣乘以 3x3矩陣),結(jié)果即為密文數(shù)字序列;
5、可將密文數(shù)字序列轉(zhuǎn)換為其對應字母,即為密文字符串。
解密:
解密流程與加密相同,唯一不同之處在于:需先求出加密密鑰的逆矩陣
在做矩陣相成時,用密文分組乘以逆矩陣,結(jié)果即為明文
代碼實現(xiàn)
#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time : 2019/12/11 14:53
# @Author : SystemDefenser
# @Email : mrwx1116@163.com
# @Software: PyCharm
from numpy import linalg
# 輸入矩陣并判斷是否存在逆矩陣
def inputMatrix():
while True:
# 輸入一行、作為行列式的階數(shù)和行列式的第一行
rank = list(input("").split())
matrix = [[0] * len(rank) for i in range(len(rank))]
matrix[0] = rank
# 輸入行列式剩余數(shù)據(jù)
for i in range(1, len(matrix)):
matrix[i] = list(input("").split())
# 判斷每一行輸入是否合法
if len(matrix[i]) != len(matrix):
print("輸入有誤,重新輸入。")
continue
# 轉(zhuǎn)換字符型為整型
for i in range(len(matrix)):
matrix[i] = list(map(lambda x: int(x), matrix[i]))
# 判斷是否存在逆矩陣
if not judgeInverse(matrix):
print("矩陣不存在逆矩陣,重新輸入。")
continue
return matrix
# 判斷是否存在逆元
def judgeInverse(matrix):
try:
linalg.inv(matrix)
except:
return False
return True
# 生成密鑰(矩陣的逆矩陣)
def createMatrixInverse(matrix):
try:
matrix_inverse = linalg.inv(matrix)
except:
return -1
return matrix_inverse
# 生成消息分組
def createMassageList(massage, matrix):
matrixRank = len(matrix)
massageList = []
# 擴充消息序列并創(chuàng)建分組
while len(massage) % matrixRank != 0:
massage += " "
for i in range(1, len(massage) + 1, matrixRank):
massageList.append(massage[i-1:i + matrixRank - 1])
return massageList
# 字母序列轉(zhuǎn)化為數(shù)字
def letterToDigit(massageList):
massageDigitList = [] # 替換后的數(shù)字列表
letterList = [] # 字母列表
for i in range(ord("a"), ord("z") + 1):
letterList.append(chr(i))
for i in range(10):
letterList.append(str(i))
# 添加空格,解決分組填充問題
letterList.append(" ")
# 替換字母為數(shù)字
for massage in massageList:
listTmp = []
for i in range(len(massage)):
listTmp.append(letterList.index(massage[i]))
massageDigitList.append(listTmp)
return massageDigitList
# 數(shù)字序列轉(zhuǎn)化為字母
def digitToLetter(massageList):
massageLetterList = [] # 還原后的字母列表
letterList = []
for i in range(ord("a"), ord("z") + 1):
letterList.append(chr(i))
for i in range(10):
letterList.append(str(i))
letterList.append(" ")
# 替換數(shù)字為字母
for massage in massageList:
massageLetterList.append(letterList[massage % 37])
return massageLetterList
# 加密
def encrypt(massage, matrix):
ciphertextList = [] # 加密結(jié)果列表
massageList = createMassageList(massage, matrix)
massageDigitList = letterToDigit(massageList)
# 矩陣相乘
for massageDigit in massageDigitList:
for i in range(len(massageDigit)):
sum = 0
for j in range(len(massageDigit)):
sum += massageDigit[j] * matrix[j][i % len(matrix)]
ciphertextList.append(sum % 37)
return ciphertextList
# 解密
def decrypt(massage, matrix):
plaintextList = [] # 解密結(jié)果列表
matrix_inverse = createMatrixInverse(matrix)
massageList = createMassageList(massage, matrix)
# 矩陣相乘
for msg in massageList:
for i in range(len(msg)):
sum = 0
for j in range(len(msg)):
sum += msg[j] * matrix_inverse[j][i % len(matrix)]
plaintextList.append(sum % 37)
# 浮點型轉(zhuǎn)換為整型(采用四舍五入——round())
plaintextList = list(map(lambda x: int(round(x)), plaintextList))
plaintextList = digitToLetter(plaintextList) # 數(shù)字轉(zhuǎn)換為字母
plaintext = ""
for item in plaintextList:
plaintext += item
return plaintext
if __name__ == "__main__":
while True: 鄭州婦科醫(yī)院 http://fk.zyfuke.com/
print("—————希爾密碼—————")
choice = input("1、加密 2、解密\n請選擇:")
if choice == "1":
print("輸入矩陣:")
matrix = inputMatrix()
massage = input("輸入msg:")
massageList = createMassageList(massage, matrix)
ciphertextList = encrypt(massage, matrix)
print("加密結(jié)果:", ciphertextList)
elif choice == "2":
massageList = list(map(int, list(input("輸入密文序列:").split(","))))
print("輸入矩陣:")
matrix = inputMatrix()
matrix_inverse = createMatrixInverse(matrix)
print("逆矩陣:")
for item in matrix_inverse:
print(item)
plaintext = decrypt(massageList, matrix)
print("解密結(jié)果:", plaintext)
其中,求逆矩陣部分未能手算,調(diào)用了numpy庫中的linalg函數(shù),慚愧………………
加密測試
—————希爾密碼—————
1、加密 2、解密
請選擇:1
輸入矩陣:
1 0 1 1
0 1 0 1
1 1 0 0
1 1 0 1
輸入msg:systemdefenser
加密結(jié)果: [18, 24, 18, 24, 11, 19, 4, 20, 36, 35, 5, 27, 2, 15, 4, 20]
—————希爾密碼—————
1、加密 2、解密
請選擇:2
輸入密文序列:18, 24, 18, 24, 11, 19, 4, 20, 36, 35, 5, 27, 2, 15, 4, 20
輸入矩陣:
1 0 1 1
0 1 0 1
1 1 0 0
1 1 0 1
逆矩陣:
[ 0. -1. 0. 1.]
[ 0. 1. 1. -1.]
[ 1. 1. 1. -2.]
[ 0. 0. -1. 1.]
解密結(jié)果: systemdefenser
加密:
解密:
部分代碼詳解
輸入矩陣部分
代碼片段:
while True:
# 輸入一行、作為行列式的階數(shù)和行列式的第一行
rank = list(input("").split())
matrix = [[0] * len(rank) for i in range(len(rank))]
matrix[0] = rank
# 輸入行列式剩余數(shù)據(jù)
for i in range(1, len(matrix)):
matrix[i] = list(input("").split())
# 判斷每一行輸入是否合法
if len(matrix[i]) != len(matrix):
print("輸入有誤,重新輸入。")
continue
該片段位于 inputMatrix() 函數(shù)中。
輸入矩陣部分未讓用戶先定義階數(shù),而是通過用戶輸入的矩陣第一行,來決定本次矩陣的階數(shù),并且不斷進行合法判斷。
解密部分
代碼片段:
# 浮點型轉(zhuǎn)換為整型(采用四舍五入——round())
plaintextList = list(map(lambda x: int(round(x)), plaintextList))
plaintextList = digitToLetter(plaintextList) # 數(shù)字轉(zhuǎn)換為字母
該片段位于 decrypt(massage, matrix) 函數(shù)中。
由于逆矩陣存在不可約分或整除的小數(shù),因此在此處采用四舍五入round(x) 的方法不嚴謹?shù)亟鉀Q此問題。