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

基于Hill Cipher的C语言加解密程序输出错误排查求助

Hill密码C程序加解密错误排查与修复

你的程序存在多个核心逻辑错误,导致加解密输出异常,以下是具体问题和修复方案:

1. 数组维度定义错误

你定义的plaintxt[2][0]、encrypted[2][0]、decrypted[2][0]都是0列数组,无法存储任何数据。Hill密码中,明文/密文是2×1的向量,应该改为:

int plaintxt[2][1], encrypted[2][1], decrypted[2][1];

2. 加密矩阵乘法逻辑错误

加密循环中,你错误地使用了plaintxt[i][0]作为乘数,导致密钥行的每个元素都乘同一个明文元素,完全不符合矩阵行乘列的规则。正确的写法应该是遍历明文的列(这里是第0列),用plaintxt[j][0]:

// 错误写法
k = k + matrix[i][j] * plaintxt[i][0];
// 正确写法
k = k + matrix[i][j] * plaintxt[j][0];

3. 解密逻辑的多重错误

3.1 密文未初始化

解密模式下,你直接使用encrypted[i][0],但这个数组在解密流程中从未被赋值,导致使用垃圾数据计算。同时,解密应该提示用户输入密文而非明文。

3.2 逆矩阵计算错误(模26下的逆)

Hill密码的逆矩阵是在模26域下计算的,不能直接用浮点数除法。正确步骤是:

  • 计算行列式的模26逆元(而非普通除法),只有当行列式与26互质时,逆元存在(你的程序只判断了行列式不为0,但没判断与26互质,比如行列式是2的话,模26没有逆元)。
  • 伴随矩阵每个元素乘逆元后再模26,得到整数形式的逆矩阵,避免浮点数精度问题。

3.3 解密乘法逻辑错误

和加密的问题一样,矩阵乘法的索引错误,应该用密文的j索引而非i索引。

4. 模运算的负数处理

当计算结果为负数时(比如伴随矩阵的负元素),直接模26会得到负数,转字符时会出错。需要先加26再取模,确保结果在0-25之间:

// 示例:处理负数
value = (value % 26 + 26) % 26;

5. 流程逻辑顺序错误

程序应该先判断命令行参数(加密/解密),再根据模式提示输入明文或密文,而非统一输入明文。


修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 计算模m下a的逆元,返回-1表示无逆元
int mod_inverse(int a, int m) {
    a = a % m;
    for (int x = 1; x < m; x++) {
        if ((a * x) % m == 1)
            return x;
    }
    return -1;
}

int main(int argc, char *argv[]) {
    int i, j, k;
    int matrix[2][2], adjoint[2][2], plaintxt[2][1], encrypted[2][1], decrypted[2][1];
    int determinant, inv_det;
    int inv_matrix[2][2]; // 改用整数存储模26下的逆矩阵
    char msg[10];

    // 检查命令行参数
    if (argc != 2 || (strcmp(argv[1], "-e") != 0 && strcmp(argv[1], "-d") != 0)) {
        printf("用法: %s [-e|-d]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 输入密钥矩阵
    printf("输入2X2密钥矩阵的元素,用空格分隔:\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            scanf("%d", &matrix[i][j]);
            // 确保密钥元素在模26范围内
            matrix[i][j] = (matrix[i][j] % 26 + 26) % 26;
        }
    }

    printf("\n密钥矩阵:\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }

    // 计算行列式并验证有效性
    determinant = (matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1]) % 26;
    // 处理负行列式
    determinant = (determinant + 26) % 26;
    if (determinant == 0) {
        printf("\n无效密钥:行列式为0,无逆矩阵。\n");
        exit(EXIT_FAILURE);
    }

    inv_det = mod_inverse(determinant, 26);
    if (inv_det == -1) {
        printf("\n无效密钥:行列式与26不互质,模26下无逆矩阵。\n");
        exit(EXIT_FAILURE);
    }

    // 计算伴随矩阵
    adjoint[0][0] = matrix[1][1];
    adjoint[1][1] = matrix[0][0];
    adjoint[0][1] = (-matrix[0][1]) % 26;
    adjoint[1][0] = (-matrix[1][0]) % 26;
    // 处理伴随矩阵的负元素
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            adjoint[i][j] = (adjoint[i][j] + 26) % 26;
        }
    }

    // 计算模26下的逆矩阵
    printf("\n模26下的逆矩阵:\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            inv_matrix[i][j] = (adjoint[i][j] * inv_det) % 26;
            inv_matrix[i][j] = (inv_matrix[i][j] + 26) % 26;
            printf("%d\t", inv_matrix[i][j]);
        }
        printf("\n");
    }

    // 根据模式输入明文/密文
    if (strcmp(argv[1], "-e") == 0) {
        printf("\n输入2个明文字符:\n");
        scanf("%s", msg);
        // 转换为0-25的整数
        for (i = 0; i < 2; i++) {
            plaintxt[i][0] = (msg[i] - 'a' + 26) % 26;
        }

        // 加密:C = K * P mod 26
        for (i = 0; i < 2; i++) {
            k = 0;
            for (j = 0; j < 2; j++) {
                k += matrix[i][j] * plaintxt[j][0];
            }
            encrypted[i][0] = (k % 26 + 26) % 26;
        }

        printf("加密后的密文: ");
        for (i = 0; i < 2; i++) {
            printf("%c", encrypted[i][0] + 'a');
        }
    } else if (strcmp(argv[1], "-d") == 0) {
        printf("\n输入2个密文字符:\n");
        scanf("%s", msg);
        // 转换为0-25的整数
        for (i = 0; i < 2; i++) {
            encrypted[i][0] = (msg[i] - 'a' + 26) % 26;
        }

        // 解密:P = K^-1 * C mod 26
        for (i = 0; i < 2; i++) {
            k = 0;
            for (j = 0; j < 2; j++) {
                k += inv_matrix[i][j] * encrypted[j][0];
            }
            decrypted[i][0] = (k % 26 + 26) % 26;
        }

        printf("解密后的明文: ");
        for (i = 0; i < 2; i++) {
            printf("%c", decrypted[i][0] + 'a');
        }
    }

    printf("\n");
    return 0;
}

内容的提问来源于stack exchange,提问作者Kadie Webb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:05:42