📜  希尔密码(1)

📅  最后修改于: 2023-12-03 15:09:42.608000             🧑  作者: Mango

希尔密码介绍

希尔密码是一种古老的对称加密技术,也被称为“多重代换密码”。该技术的核心思想是将明文分组,每组分别进行转换,最终得到密文。

加密步骤
  1. 选择密钥:选择一个正整数$d$作为密钥,会根据密钥决定有多少组明文以及每组的长度。
  2. 分组明文:将明文按照密钥$d$进行分组,每组长度为$d$。
  3. 转换明文:对于每组明文,进行代换操作,将明文字符在指定范围内以固定间隔互相替换。
  4. 生成密文:将代换后的每组明文拼接在一起,得到密文。
解密步骤
  1. 选择密钥:选择密文加密时采用的密钥$d$。
  2. 分组密文:将密文按照密钥$d$进行分组,每组长度为$d$。
  3. 解密明文:对于每组密文,进行逆代换操作,将密文字符在指定范围内以固定间隔互相替换。
  4. 生成明文:将逆代换后的每组明文拼接在一起,得到明文。
Python 实现
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