为什么我的小写字母 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';
}
为什么 encryptLower()
以错误的方式加密小写文本?虽然我们知道规则是:
Ei = (Pi + Ki) mod 26
并解密:
Di = (Ei - Ki + 26) mod 26
为什么在加密小写字母时,我需要从密钥和明文字符中减去 a
的值,然后求和和 mod 26?为什么我不需要大写字母?
我的通用 encrypt()
和 decrypt
函数是否正确?谢谢!
我确定问题出在这里:
char P = 'H'; // 72
char K = 'A'; // 65
char C = (P + K) % 26; // 7
C += 'A'; // 7 + 'A' = H
std::cout << C << '\n'; // H
char p = 'h'; // 104
char k = 'a'; // 97
char c = (p + k) % 26; // 19
c += 'a'; // 19 + 'a' = t
std::cout << c << '\n'; // t
通常使用密钥 a
或 A
会产生与大写字母一样不变的加密字符,但为什么不能使用小写字母?
考虑 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 上调试和发布代码的一些提示:您的代码的输出在方法的第一个字母中是错误的,所以那里出了问题。如果你只考虑那个最小的例子,就更容易发现错误。因此,请尝试生成一个最小的可重现示例。
我试过实施 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';
}
为什么
encryptLower()
以错误的方式加密小写文本?虽然我们知道规则是:Ei = (Pi + Ki) mod 26
并解密:
Di = (Ei - Ki + 26) mod 26
为什么在加密小写字母时,我需要从密钥和明文字符中减去
a
的值,然后求和和 mod 26?为什么我不需要大写字母?我的通用
encrypt()
和decrypt
函数是否正确?谢谢!我确定问题出在这里:
char P = 'H'; // 72 char K = 'A'; // 65 char C = (P + K) % 26; // 7 C += 'A'; // 7 + 'A' = H std::cout << C << '\n'; // H char p = 'h'; // 104 char k = 'a'; // 97 char c = (p + k) % 26; // 19 c += 'a'; // 19 + 'a' = t std::cout << c << '\n'; // t
通常使用密钥
a
或A
会产生与大写字母一样不变的加密字符,但为什么不能使用小写字母?
考虑 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 上调试和发布代码的一些提示:您的代码的输出在方法的第一个字母中是错误的,所以那里出了问题。如果你只考虑那个最小的例子,就更容易发现错误。因此,请尝试生成一个最小的可重现示例。