C ++ функция для шифра vigenere, который иногда работает (работает для одних входов, пропускает смены для других) - PullRequest
0 голосов
/ 20 июня 2019

Для назначения в классе я должен был написать функцию, которая помещает строку ввода пользователя через шифр Vigenere с дополнительной помощью вспомогательной функции. Мне удалось найти частичное решение, используя вспомогательную функцию, которая получает правильный сдвиг для символа на основе его места в алфавите, а также другую функцию, которая сдвигает символы в строке на это место, если они являются буквами.

Программа работает только с одним примером: «Привет, мир!» с ключевым словом «торт», должным образом зашифрованным в «Jevpq, Wyvnd!», однако ввод автогрейдерами «hDcT + T EtL5V71» и ключевое слово «vpkbncc» возвращает «cSmU + V OuY5Q71» вместо «cSmU +» G GvG5K71 ". Я знаю, почему это происходит; первый символ пропускается через каждую итерацию, поэтому «торт» в конечном итоге становится «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;    

}

Как я уже говорил, «Здравствуй, мир!» пример работает, хотя первый символ в торт по какой-то причине пропущен в цикле for:

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__, что неверно.

Кто-нибудь знает, как я могу исправить это?

1 Ответ

0 голосов
/ 20 июня 2019

Ваша проблема здесь не в том, что игнорируется первая буква ключевого слова (попробуйте 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;    

}
...