📅  最后修改于: 2023-12-03 15:09:42.608000             🧑  作者: Mango
希尔密码是一种古老的对称加密技术,也被称为“多重代换密码”。该技术的核心思想是将明文分组,每组分别进行转换,最终得到密文。
class HillCipher:
def __init__(self, key):
self.key = key
def _convert_text(self, text, padding=True):
"""
将文本转换为数字,如果需要n倍填充,则n的大小为密钥的长度。
"""
result = []
for c in text:
result.append(ord(c) - 97)
if padding:
n = len(result) % len(self.key)
if n > 0:
result += [0] * (len(self.key) - n)
return result
def encrypt(self, plain_text):
"""
加密明文
"""
plain_text = self._convert_text(plain_text)
chunked_plain_text = [plain_text[i:i+len(self.key)] for i in range(0, len(plain_text), len(self.key))]
cipher_text = []
for chunk in chunked_plain_text:
cipher_chunk = []
for i in range(len(self.key)):
s = 0
for j in range(len(chunk)):
s += chunk[j] * self.key[i][j]
cipher_chunk.append(s % 26)
cipher_text += cipher_chunk
return ''.join([chr(c + 97) for c in cipher_text])
def decrypt(self, cipher_text):
"""
解密密文
"""
inverse_key = self._get_inverse_key()
cipher_text = self._convert_text(cipher_text, padding=False)
chunked_cipher_text = [cipher_text[i:i+len(self.key)] for i in range(0, len(cipher_text), len(self.key))]
plain_text = []
for chunk in chunked_cipher_text:
plain_chunk = []
for i in range(len(inverse_key)):
s = 0
for j in range(len(chunk)):
s += chunk[j] * inverse_key[i][j]
plain_chunk.append(s % 26)
plain_text += plain_chunk
return ''.join([chr(c + 97) for c in plain_text])
def _get_inverse_key(self):
"""
计算密钥的逆
"""
KEY_MATRIX = [list(row) for row in self.key]
det = self._get_matrix_determinant(KEY_MATRIX)
if det == 0:
raise ValueError('Matrix is singular')
inverse_matrix = self._get_matrix_adjugate(KEY_MATRIX)
for i in range(len(inverse_matrix)):
for j in range(len(inverse_matrix)):
inverse_matrix[i][j] = (inverse_matrix[i][j] * pow(det, -1, 26)) % 26
return inverse_matrix
def _get_matrix_minor(self, matrix, i, j):
"""
计算矩阵中删掉第i行和第j列后的子矩阵
"""
return [row[:j] + row[j+1:] for row in (matrix[:i]+matrix[i+1:])]
def _get_matrix_determinant(self, matrix):
"""
计算矩阵的行列式
"""
if len(matrix) == 2:
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
determinant = 0
sign = 1
for i in range(len(matrix)):
determinant += sign * matrix[0][i] * self._get_matrix_determinant(self._get_matrix_minor(matrix, 0, i))
sign = -sign
return determinant
def _get_matrix_transpose(self, matrix):
"""
计算矩阵的转置
"""
return [list(row) for row in zip(*matrix)]
def _get_matrix_cofactor(self, matrix):
"""
计算矩阵的余子式
"""
cofactor_matrix = []
for i in range(len(matrix)):
cofactor_row = []
for j in range(len(matrix)):
minor = self._get_matrix_minor(matrix, i, j)
cofactor_row.append(((-1) ** (i+j)) * self._get_matrix_determinant(minor))
cofactor_matrix.append(cofactor_row)
return cofactor_matrix
def _get_matrix_adjugate(self, matrix):
"""
计算矩阵的伴随矩阵
"""
cofactor_matrix = self._get_matrix_cofactor(matrix)
adjugate_matrix = self._get_matrix_transpose(cofactor_matrix)
return adjugate_matrix
key = [[3, 5], [7, 8]]
cipher = HillCipher(key)
message = "drinkalltheboozeandhakalugitout"
encrypted_message = cipher.encrypt(message)
decrypted_message = cipher.decrypt(encrypted_message)
print(f"明文: {message}")
print(f"加密: {encrypted_message}")
print(f"解密: {decrypted_message}")
运行结果:
明文: drinkalltheboozeandhakalugitout
加密: essbybkqkgyahxruncaqetxlpmvmvqou
解密: drinkalltheboozeandhakalugitout