为什么我的小写字母 Vigenere 加密功能不能正常工作?

Why my Vigenere encryption function for small letters doesn't work correctly?

我试过实施 Vigenere 的 Cypher。我发现它与大写字母一起使用,但我已经让它适用于大写字母和小写字母,但纯文本或加密文本的字符必须与密钥中相应的字符相同。所以我这样做了:

std::string encryptUpper(std::string const& plain, std::string const& key){
    std::string cyphered;
    for(std::size_t i = 0, j = 0, plainLen = plain.length(), keyLen = key.length();
        i != plainLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        cyphered += ( (plain.at(i) + key.at(j) ) % 26) + 'A';
    }
    return cyphered;
}

std::string decryptUpper(std::string const& cyphered, std::string const& key){
    std::string plain;
    for(std::size_t i = 0, j = 0, cypheredLen = cyphered.length(), keyLen = key.length();
        i != cypheredLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        plain += ( ( (cyphered.at(i) - key.at(j) + 26) % 26) + 'A');
    }
    return plain;
}

std::string encryptLower(std::string const& plain, std::string const& key){
    std::string cyphered;
    for(std::size_t i = 0, j = 0, plainLen = plain.length(), keyLen = key.length();
        i != plainLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        cyphered += ( (plain.at(i) + key.at(j) ) % 26) + 'a';
    }
    return cyphered;
}

std::string decryptLower(std::string const& cyphered, std::string const& key){
    std::string plain;
    for(std::size_t i = 0, j = 0, cypheredLen = cyphered.length(), keyLen = key.length();
        i != cypheredLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        plain += ( (cyphered.at(i) - key.at(j) + 26 ) % 26) + 'a';
    }
    return plain;
}


std::string encrypt(std::string const& plain, std::string const& key){
    std::string cyphered;
    for(std::size_t i = 0, j = 0, plainLen = plain.length(), keyLen = key.length();
        i != plainLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        cyphered += ( (plain.at(i) - (std::isupper(plain.at(i)) ? 'A' : 'a') + key.at(j) - (std::isupper(plain.at(i)) ? 'A' : 'a') ) % 26) +
        (std::isupper(plain.at(0)) ? 'A' : 'a');
    }
    return cyphered;
}

std::string decrypt(std::string const& cyphered, std::string const& key){
    std::string plain;
    for(std::size_t i = 0, j = 0, cypheredLen = cyphered.length(), keyLen = key.length();
        i != cypheredLen; ++i, ++j){
        if(j == keyLen)
            j = 0;
        plain += ( (cyphered.at(i) - key.at(j) + 26 ) % 26) +
        (std::isupper(cyphered.at(i)) ? 'A' : 'a');
    }
    return plain;
}

int main(){

    std::string s1 = "HELLO";
    std::string key1 = "ATOM";
    auto cyphered1 = encryptUpper(s1, key1);
    std::cout << cyphered1 << '\n';
    auto plain = decryptUpper(cyphered1, key1);
    std::cout << plain << '\n';

    std::string s2 = "hello";
    std::string key2 = "atom";

    auto cyphered2 = encryptLower(s2, key2);
    std::cout << cyphered2 << '\n';
    auto plain2 = decryptLower(cyphered2, key2);
    std::cout << plain2 << '\n';

    cyphered2 = encrypt(s2, key2);
    std::cout << cyphered2 << '\n';
    plain2 = decryptLower(cyphered2, key2);
    std::cout << plain2 << '\n';

    std::cout << "=========\n";
    auto c1 = encrypt(s1, key1);
    auto p1 = decrypt(c1, key1);
    std::cout << c1 << '\n' << p1 << '\n';

    auto c2 = encrypt(s2, key2);
    auto p2 = decrypt(c2, key2);
    std::cout << c2 << '\n' << p2 << '\n';
}

并解密:

  Di = (Ei - Ki + 26) mod 26

考虑 Ascii Table:http://www.asciitable.com/。 如果您将字符写为 (65+i)(65+j) 并添加它们,使用大写方法,您将得到 65+(65+i)+(65+j) \equiv 65+i+j \mod 26。 你很幸运 65 + 65 可以被大写的 26 整除!

对于小写字母,我们 97+97 不能被 26 整除。

SO 上调试和发布代码的一些提示:您的代码的输出在方法的第一个字母中是错误的,所以那里出了问题。如果你只考虑那个最小的例子,就更容易发现错误。因此,请尝试生成一个最小的可重现示例。