Vigenere Cipher - 莫名其妙的细微差别

Posted

技术标签:

【中文标题】Vigenere Cipher - 莫名其妙的细微差别【英文标题】:Vigenere Cipher - Inexplicable Nuance 【发布时间】:2016-10-15 00:12:16 【问题描述】:

我正在 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)

【问题讨论】:

@user3386109 已更正 在原始代码中,k_index 每次循环都被设置回0。更新后的代码在开始时将其设置为0,然后在循环期间将其递增。 @Barmar 啊啊啊我明白了!这就是为什么至少第一个字符在原始代码中总是正确的! 变量不是唯一的变化。您还更改了“加密”行。 @WeatherVane 是的,但是加密线背后的数学仍然是一样的。只是'letter_key'的计算之前已经完成了。 【参考方案1】:

原来的代码是这样的:

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 的更新值。这正确地使用了整个密钥。

【讨论】:

以上是关于Vigenere Cipher - 莫名其妙的细微差别的主要内容,如果未能解决你的问题,请参考以下文章

Vigenere Cipher - 解密(手动)

Vigenere Cipher - 解密(手动)

PSET 2:Vigenere Cipher 部分工作?

Vigenere Cipher - 不给信[关闭]

Vigenere Cipher使用命令行提示

Vigenere Cipher 没有错误消息 Python