Vigenere Cipher - 难以理解的Nuance

时间:2016-10-15 00:12:17

标签: c algorithm encryption cs50 vigenere

我在C中实现了一个Vigenere密码。我的解决方案不正确地加密了纯文本。因此我决定对我的代码做一些(有点武断的)改变。更改的目的只是为了使代码更具可读性,方法是更好地定位我的变量,并为它们提供更合适的名称。但是,这种变化现在已经使解决方案正确地加密; 我无法解释为什么当前解决方案适用于原始解决方案 。有人可能会启发我吗?

original.c

//...code to validate user input

string k = argv[1]; //'argv' being a main method parameter
string str = GetString();

//Encrypt using vigenere
for (int i = 0, n = strlen(str); i < n; i++) {

    /*An int to keep track of which char to use from the keyword.
    Only increment if str[i] was alphabetic.*/
    int k_index = 0;
    int k_len = strlen(k);
    char letter_key = tolower(k[k_index % k_len]);

    //Checking if str[i] is alphabetic
    if (isalpha(str[i])) {

        //Checking if str[i] is uppercase
        if (isupper(str[i])) {

            //enciphering using vigenere formula
            str[i] = ((str[i] - 'A') + (letter_key - 'a')) % 26 + 'A';
            printf("%c", str[i]);
            k_index++;
        }

        //If not uppercase, it must be lowercase
        else {
            //enciphering using vigenere formula
            str[i] = ((str[i] - 'a') + (letter_key - 'a')) % 26 + 'a';
            printf("%c", str[i]);
            k_index++;
        }

    } else {
        printf("%c", str[i]);
    }
}

输出

Key: "chasi"
Input/Result: "my plaintext" ---> "oa rnckpvgzv" 
Should be: "of pdikutwfv"

updated.c

//...code to validate user input

string k = argv[1];
string str = GetString();

//Encrypt using vigenere
for (int i = 0, j = 0, n = strlen(str); i < n; i++) {

    /*"int j" is to keep track of which char to use from the keyword.
    Only increment if str[i] was alphabetic.*/

    int k_len = strlen(k);
    char letter_key = tolower(k[j % k_len]) - 'a';

    //Checking if str[i] is alphabetic
    if (isalpha(str[i])) {

        //Checking if str[i] is uppercase
        if (isupper(str[i])) {

            //enciphering using vigenere formula
            str[i] = ((str[i] - 'A') + letter_key) % 26 + 'A';
            printf("%c", str[i]);
            j++;
        }

        //If not uppercase, it must be lowercase
        else {
            //enciphering using vigenere formula
            str[i] = ((str[i] - 'a') + letter_key) % 26 + 'a';
            printf("%c", str[i]);
            j++;
        }

    } else {
        printf("%c", str[i]);
    }
}

输出:

Key: "chasi"
Input/Result: "my plaintext" ---> "of pdikutwfv" (correct)

1 个答案:

答案 0 :(得分:3)

原始代码确实:

int k_index = 0;

每次循环。然后当它:

char letter_key = tolower(k[k_index % k_len]);

它正在使用此0值,因此letter_key始终为tolower(k[0])。它所做的地方k_index++;没有效果,因为变量在再次使用之前会被归零。所以你只是使用键的第一个字符作为整个键。

在更新的代码中,变量j取代k_index。它在循环开始时被初始化为0,而不是每次循环。所以当你这样做时:

char letter_key = tolower(k[j % k_len]) - 'a';

您正在使用j的更新值。这恰当地使用了整个密钥。