问题描述
我尝试过实施 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,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,++j){
if(j == keyLen)
j = 0;
cyphered += ( (plain.at(i) + key.at(j) ) % 26) + 'a';
}
return cyphered;
}
std::string decryptLower(std::string const& cyphered,++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,++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,++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 表:http://www.asciitable.com/。
如果您将字符写为 (65+i)
和 (65+j)
并使用大写方法添加它们,您将得到 65+(65+i)+(65+j) \equiv 65+i+j \mod 26
。
您很幸运,65 + 65
可以被大写的 26 整除!
对于小写字母,我们没有可以被 26 整除的 97+97
。
在 SO 上调试和发布代码的一些提示:您的代码输出在方法的第一个字母中是错误的,所以那里出了点问题。如果你只考虑这个最小的例子,就更容易发现错误。因此,请尝试生成一个可重现的最小示例。