用于 vigenere 密码的 C++ 函数仅有时有效(适用于某些输入,跳过其他输入)

C++ function for vigenere cipher only sometimes working (works for some inputs, skips shifts for others)

对于 class 中的作业,我必须编写一个函数,在辅助函数的可选帮助下,通过 vigenere 密码输入用户输入的字符串。我能够使用一个辅助函数获得部分解决方案,该函数根据字符在字母表中的位置获得正确的字符移位,以及另一个函数,如果它们是字母,则将字符串中的字符移位到这个位置。

该程序偶尔会使用一个示例 "Hello, world!",关键字 "cake" 被正确加密为 "Jevpq, Wyvnd!",但是自动评分器的输入 "hDcT+T EtL5V71" 和关键字 "vpkbncc" returns "cSmU+V OuY5Q71" 而不是 "cSmU+G GvG5K71"。我知道为什么会这样;每次迭代都会跳过第一个字符,因此 "cake" 最终成为 "ake",但我不知道如何解决这个问题。这是我的代码:

/*Author: Xavier f.*/

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

using namespace std;

int getShift(char c); // helper function that converts chars into their place in the alphabet as an int 
char shiftChar(char c, int rshift); // this function handles the character value shifting part of the problem
string encryptVigenere(string plaintext, string keyword); //implemntation of Vigenere cypher  , needs to loop around keyword


int main(){ 

    string text, key, debug; 
    cout << "Enter a sentence: ";
    getline(cin, text); 
    cout << "Enter the keyword  : "; 
    getline(cin, key); 

    debug = encryptVigenere(text, key);
    cout << "Ciphertext     : " << debug;  

    return 0; 

}

int getShift(char c) { 

    if (isupper(c)) { 

        return (int)c-(int)'A';
    }
    else { 

        return (int)c-(int)'a';

    }


}  

char shiftChar(char c, int rshift) { 

    char shifted;


    if (isalpha(c)) { //if it is a letter

        if (isupper(c)){

            shifted = ((int)c + rshift - 'A')%26 + 'A';        //65-90 for uppercase , 97-122 for lowercase
        } 
        else { //dont have to put condition since if its not uppercase its obviously lowercase  

            shifted = ((int)c + rshift - 'a')%26 + 'a'; 

        } 

        return shifted;
    } 
    else { 

        return c; 

    } 

} 

string encryptVigenere(string plaintext, string keyword){ 

    char encrypted;
    string vigenere; 
    int ciphercount = 0;

        for(int i = 0; i < plaintext.length(); ++i) {

            if(isalpha(plaintext[i])) {

                encrypted = shiftChar(plaintext[i], getShift(keyword[ciphercount])); 
                vigenere += encrypted; 
                ciphercount ++;

            } 
            else { 
                ciphercount -= keyword.length();
                vigenere += plaintext[i]; 
            }
            ciphercount = ciphercount % keyword.length();
        }  

    return vigenere;    

}

就像我之前提到的,即使 cake 中的第一个字符由于某种原因在 for 循环中被跳过,"Hello, world!" 示例仍然有效:

Enter a sentence: Hello, world!
Enter the keyword  : cake
Ciphertext     : Jevpq, wyvnd! 

debug: og ciphercount: c/ debug: plaintext[i]: H / debug: keyword[ciphercount]: a / debug: cyphercount isalpha: 1 / debug: encrypted: J / debug: vigenere: J
debug: cyphercount loop through: 1

然而,随着自动评分者的输入,这个问题变得更加灾难性:

Enter a sentence: hDcT+T EtL5V71
Enter the keyword  : vpkbncc
Ciphertext     : cSmU+V OuY5Q71 

debug: og ciphercount: v / debug: plaintext[i]: h / debug: keyword[ciphercount]: p / debug: cyphercount isalpha: 1 / debug: encrypted: c / debug: vigenere: c
debug: cyphercount loop through: 1

输出应该是 "cSmU+G GvG5K71",但是由于跳过了第一个换档字符,所以输入的文字是 pkbn_bn_c_p__,这是错误的。

有人知道我该如何解决这个问题吗?

这里的问题不是关键字的第一个字母被忽略(尝试 fake 而不是 cake 并确认它确实改变了输出)。

看来您真正的问题在于 encryptVigenere 函数的编写方式。

我不是密码学专家,我不能告诉你这是否是实现 vigenere 密码的正确方法,但我无法理解这一行:

            ciphercount -= keyword.length();

事实证明,如果删除它,您将获得想要的结果。

那么,这是您的新 encryptVigenere 函数:

string encryptVigenere(string plaintext, string keyword){ 

    char encrypted;
    string vigenere; 
    int ciphercount = 0;

        for(int i = 0; i < plaintext.length(); ++i) {

            if(isalpha(plaintext[i])) {
                encrypted = shiftChar(plaintext[i], getShift(keyword[ciphercount])); 
                vigenere += encrypted; 
                ciphercount ++;
            } 
            else { 
                //ciphercount -= keyword.length();
                vigenere += plaintext[i]; 
            }
            ciphercount = ciphercount % keyword.length();
        }  

    return vigenere;    

}