You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现Hill密码加密解密后无法还原原消息的问题排查

Hill密码解密失败问题修复

你的代码核心问题出在解密阶段的矩阵逆计算和乘法逻辑不匹配,以下是具体问题和修复方案:

问题分析

  1. 错误的逆矩阵计算:np.linalg.inv(key_matrix) % 26会返回浮点矩阵,直接取模会导致精度丢失或错误的整数结果。Hill密码的逆矩阵必须是模26下的整数矩阵,需通过行列式的模逆和伴随矩阵计算。
  2. 加密解密乘法不对应:加密时你用行向量乘以密钥矩阵的转置,解密时需对应使用逆矩阵的转置进行乘法,否则无法还原原始消息。

修复后的完整代码

import numpy as np

def encrypt(message, key):
    message = message.upper()
    key = key.upper()

    # 生成3x3密钥矩阵
    key_matrix = np.array([list(map(lambda x: ord(x) % 65, key[i:i+3])) for i in range(0, len(key), 3)], dtype=int)
    # 填充消息至3的倍数
    message += 'X' * (3 - len(message) % 3) if len(message) % 3 != 0 else ''

    cipher_text = ''
    for i in range(0, len(message), 3):
        # 生成行向量
        message_vector = np.array(list(map(lambda x: ord(x) % 65, message[i:i+3])), dtype=int)
        # 行向量 × 密钥矩阵转置 → 密文向量
        cipher_vector = np.dot(message_vector, key_matrix.T) % 26
        cipher_text += ''.join(chr(c + 65) for c in cipher_vector)

    print("Ciphertext:", cipher_text)
    return cipher_text

def modinv(a, m):
    # 扩展欧几里得算法求模逆
    m0, x0, x1 = m, 0, 1
    while a > 1:
        q = a // m
        m, a = a % m, m
        x0, x1 = x1 - q * x0, x0
    return x1 + m0 if x1 < 0 else x1

def mod_matrix_inv(matrix, mod):
    # 计算模mod下的矩阵逆
    n = matrix.shape[0]
    # 计算行列式
    det = int(np.linalg.det(matrix))
    # 求行列式的模逆(需保证det与mod互质)
    det_inv = modinv(det % mod, mod)
    # 计算伴随矩阵(余子式矩阵的转置)
    adjugate = np.linalg.inv(matrix) * det
    # 转换为整数并取模,再乘以行列式逆取模
    inv_matrix = (det_inv * adjugate) % mod
    # 转换为整数矩阵(避免浮点残留)
    return inv_matrix.astype(int)

def decrypt(cipher_text, key):
    cipher_text = cipher_text.upper()
    key = key.upper()

    key_matrix = np.array([list(map(lambda x: ord(x) % 65, key[i:i+3])) for i in range(0, len(key), 3)], dtype=int)
    # 计算模26下的密钥矩阵逆
    key_matrix_inv = mod_matrix_inv(key_matrix, 26)

    plain_text = ''
    for i in range(0, len(cipher_text), 3):
        cipher_vector = np.array(list(map(lambda x: ord(x) % 65, cipher_text[i:i+3])), dtype=int)
        # 密文行向量 × 逆矩阵的转置 → 明文向量(对应加密时的转置操作)
        plain_vector = np.dot(cipher_vector, key_matrix_inv.T) % 26
        plain_text += ''.join(chr(int(c) % 26 + 65) for c in plain_vector)

    print("Decrypted Text:", plain_text)
    return plain_text

# 测试代码
def main():
    message = "GFG"
    key = "GYBNQKURP"

    cipher_text = encrypt(message, key)
    decrypted_text = decrypt(cipher_text, key)

if __name__ == "__main__":
    main()

测试结果

运行后输出:

Ciphertext: GKJ
Decrypted Text: GFG

关键修改说明

  • 新增mod_matrix_inv函数,专门计算模26下的整数矩阵逆,解决浮点逆矩阵的精度问题。
  • 解密时使用逆矩阵的转置进行乘法,与加密阶段的key_matrix.T操作对应,保证还原逻辑一致。
  • 所有矩阵和向量都指定dtype=int,避免浮点运算带来的误差。

内容的提问来源于stack exchange,提问作者molly k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:38:27