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

Vigenere Cipher加解密程序逻辑故障求助:无法还原原消息

问题排查与解决方案

我帮你仔细梳理了代码里的问题,主要有几个关键点导致加密后解密无法还原原消息,下面逐一说明并给出修复方案:

1. 字符未转换为0-25范围直接计算

不管加密还是解密,你直接用字符的ASCII值进行加减取模,但大写字母的ASCII是从65('A')开始的,直接相加会远大于26,完全偏离了维吉尼亚密码的计算逻辑。

加密函数的错误

原代码:

int x = (message[i] + key[i]) %26;

正确做法:先把每个字符转换成0-25的偏移量(减去'A'),再执行加密计算:

int x = ( (message[i] - 'A') + (key[i] - 'A') ) % 26;

解密函数的错误

原代码:

int x = (message[i] - key[i] + 26) %26;

同样需要先转成0-25的偏移量,加26是为了避免负数取模的异常:

int x = ( (message[i] - 'A') - (key[i] - 'A') + 26 ) % 26;

2. 密钥扩展逻辑错误

你当前的密钥扩展循环逻辑有问题,应该基于原始密钥的长度来循环重复,而不是消息长度。原代码里的重置条件if (x == i) i = 0;(x是消息长度)会导致错误的密钥重复模式,比如密钥长度为3、消息长度为5时,会生成不符合预期的扩展密钥。

修正后的密钥扩展逻辑可以简化为:

int originalKeyLen = key.size();
while (key.size() < message.size()) {
    key.push_back(key[key.size() % originalKeyLen]);
}

3. 未统一转换输入为大写

虽然提示里说会将消息转成大写,但代码里没有处理这个逻辑。如果用户输入小写字母,ASCII值和大写不同,会直接导致计算错误。我们可以添加一个辅助函数统一转换大小写:

string toUpperCase(string s) {
    for (char &c : s) {
        c = toupper(c);
    }
    return s;
}

然后在获取输入时调用这个函数,确保消息和密钥都是大写格式。


修正后的完整代码

#include <iostream>
#include <string>
#include <cctype>

using namespace std;

// 辅助函数:转换字符串为大写
string toUpperCase(string s) {
    for (char &c : s) {
        c = toupper(c);
    }
    return s;
}

// 给用户展示信息
int giveInfo(){
    cout << "\nThe Vigenere Cypher is a polyalphabetic encryption/decryption method. It utilizes a 'key' (provided by the user, \nany word of any length) to determine which letters will replace others. This means in order to decrypt a message,\n one will need the key the person who encrypted the message used, ensuring a secure encryption. To use this program, \nyou will need to enter your message (this will be converted into all capital letters) and a key which you would like to use. Do not use any spaces in your message.\n\n\n";
    return 0;
}

// 获取用户消息
string messageInput(){
    string userMessage;
    cout << "What is the message you would like to encrypt/decrypt?\n";
    cin >> userMessage;
    return toUpperCase(userMessage);
}

// 获取用户密钥
string keyInput(){
    string userKey;
    cout << "What is the key you would like to use?\n";
    cin >> userKey; 
    return toUpperCase(userKey);
}

// 解密函数
void decrypt(string message, string key){
    // 扩展密钥到消息长度
    int originalKeyLen = key.size();
    while (key.size() < message.size()) {
        key.push_back(key[key.size() % originalKeyLen]);
    }

    string orig_text;
    for (int i = 0 ; i < message.size(); i++)
    {
        // 转换为0-25范围计算
        int x = ( (message[i] - 'A') - (key[i] - 'A') + 26 ) % 26;
        // 转换回ASCII大写字母
        x += 'A';
        orig_text.push_back(x);
    }

    cout << "\n\nEncrypted Code: " << message << "\n";
    cout << "Key: " << key << "\n";
    cout << "Decrypted message: " << orig_text << "\n";
}

// 加密函数
void encrypt(string message, string key){
    // 扩展密钥到消息长度
    int originalKeyLen = key.size();
    while (key.size() < message.size()) {
        key.push_back(key[key.size() % originalKeyLen]);
    }

    string cipher_text;
    for (int i = 0; i < message.size(); i++)
    {
        // 转换为0-25范围计算
        int x = ( (message[i] - 'A') + (key[i] - 'A') ) % 26;
        // 转换回ASCII大写字母
        x += 'A';
        cipher_text.push_back(x);
    }

    cout << "\n\nOriginal message: " << message << "\n";
    cout << "Key: " << key << "\n";
    cout << "Encrypted message: " << cipher_text << "\n";
}

// 获取用户选择
int userChoice(){
    int choice;
    cout << "Would you like to encrypt a message or decrypt a message? (1 = encrypt, 2 = decrypt)\n";
    cin >> choice;
    return choice;
}

int main(){
    giveInfo();

    // 循环支持多次加密解密
    int counter = 1;
    int userCounter;

    while (counter == 1){
        int choice = userChoice();

        if(choice == 1){
            string inputMessage = messageInput();
            string inputKey = keyInput();
            encrypt(inputMessage, inputKey);
        } else {
            string inputMessage = messageInput();
            string inputKey = keyInput();
            decrypt(inputMessage, inputKey);
        }

        cout << "Would you like to decrypt/encrypt another message? (1 = yes, 2 = no)";
        cin >> userCounter;
        counter = userCounter;
        system("CLS");
    }

    return 0;
}

测试验证

比如输入消息HELLO,密钥KEY:

  • 加密后会得到RIJVS
  • 用密钥KEY解密RIJVS,会正确还原为HELLO

现在修正后的代码应该可以正常工作了,你可以测试看看。

内容的提问来源于stack exchange,提问作者Clyde Tamburro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:26:11