仿射密码解密,输出大小写不同

Affine cipher decryption, output differs for upper case and lower case

本文关键字:大小写 输出 密码 解密      更新时间:2023-10-16

使用仿射密码解密明文时遇到问题。 加密工作正常,但对小写/大写字符的解密应用相同的逻辑会返回不同的输出。

这是输出:

Encrypted Message is :ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD
Decrypted Message is: opqrstuvwxyzabcdefghijklmn ABCDEFGHIJKLMNOPQRSTUVWXYZ

我怀疑这与检索 ASCII 值有关,有人可以纠正我吗?

这是我的代码:

#include<bits/stdc++.h> 
using namespace std; 
//Key values of a and b 
const int a = 17; 
const int b = 20; 
string encryptMessage(string plainText) 
{ 
string cipher = ""; 
for (int i = 0; i < plainText.length(); i++) 
{ 
if(plainText[i]!=' ') 
{
if ((plainText[i] >= 'a' && plainText[i] <= 'z') || (plainText[i] >= 'A' && plainText[i] <= 'Z'))
{
if (plainText[i] >= 'a' && plainText[i] <= 'z')
{
cipher = cipher + (char) ((((a * (plainText[i]-'a') ) + b) % 26) + 'a'); 
}
else if (plainText[i] >= 'A' && plainText[i] <= 'Z')
{
cipher = cipher + (char) ((((a * (plainText[i]-'A') ) + b) % 26) + 'A');
}
}
else
{
cipher += plainText[i]; 
}
}
else
{
cipher += plainText[i]; 
}
} 
return cipher; 
} 
string decryptCipher(string cipher) 
{ 
string plainText = ""; 
int aInverse = 0; 
int flag = 0; 
for (int i = 0; i < 26; i++) 
{ 
flag = (a * i) % 26; 
if (flag == 1) 
{ 
aInverse = i; 
} 
} 
for (int i = 0; i < cipher.length(); i++) 
{ 
if(cipher[i] != ' ') 
{
if ((cipher[i] >= 'a' && cipher[i] <= 'z') || (cipher[i] >= 'A' && cipher[i] <= 'Z'))
{
if (cipher[i] >= 'a' && cipher[i] <= 'z')
{
plainText = plainText + (char) ((((aInverse * (cipher[i]+ 'a') ) - b) % 26) + 'a'); 
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z')
{
plainText = plainText + (char) (((aInverse * ((cipher[i]+'A' - b)) % 26)) + 'A'); 
}
}
else
{
plainText += cipher[i]; 
}           
}
else
plainText += cipher[i]; 
} 
return plainText; 
} 
//Driver Program 
int main(void) 
{ 
string msg = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
//Calling encryption function 
string cipherText = encryptMessage(msg); 
cout << "Encrypted Message is : " << cipherText<<endl; 
//Calling Decryption function 
cout << "Decrypted Message is: " << decryptCipher(cipherText); 
return 0; 
} 

我已经考虑了一段时间,虽然我不能提供完整的解释,但我有几个可能有用的"观察",以及一个"作弊"解决方法。

首先,尽管您说使用"相同的逻辑解密小写/大写">,但每个解密块的代码的字符对齐表明这并不完全正确:

plainText = plainText + (char) ((((aInverse * (cipher[i]+ 'a') ) - b) % 26) + 'a'); // Lower case
plainText = plainText + (char) (((aInverse * ((cipher[i]+'A' - b)) % 26)) + 'A');   // Upper case

因此,将小写代码"修复"为与大写的(工作(代码完全相似(并删除多余的括号(会得到:

if (cipher[i] >= 'a' && cipher[i] <= 'z')
{
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'a' - b) ) % 26 ) + 'a' );
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z')
{
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'A' - b) ) % 26 ) + 'A' );
}

但是,这实际上并不能解决问题(它只是略有更改(,因为输出如下:

Encrypted Message is : ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD
Decrypted Message is : qrstuvwxyzabcdefghijklmnop ABCDEFGHIJKLMNOPQRSTUVWXYZ

这里的问题是小写值都由值16"旋转"——这看起来可疑地接近a的值。另请注意,尽管加密公式中使用了a,但它不会用于解密。

因此,我想出了以下解决方法,假设(由于尚未推断的原因(在解码大写值时,此16在 ASCII 值的位表示中以某种方式丢失:

if ((cipher[i] >= 'a' && cipher[i] <= 'z') || (cipher[i] >= 'A' && cipher[i] <= 'Z'))
{
int offset = ((cipher[i] - 'A') / 26) ? a - 1 : 0;
if (cipher[i] >= 'a' && cipher[i] <= 'z') {
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'a' - b) - offset ) % 26 ) + 'a' );
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z') {
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'A' - b) - offset ) % 26 ) + 'A' );
}
}

请注意,使用标准库提供的函数并删除一些"冗余"检查,可以进一步简化/澄清您的代码:

for (int i = 0; i < cipher.length(); i++) {
if (isalpha(cipher[i])) {
int offset = islower(cipher[i]) ? a - 1 : 0;
int letter = islower(cipher[i]) ? 'a' : 'A';
plainText = plainText + (char)(((aInverse * (cipher[i] + letter - b) - offset) % 26) + letter);
}
else {
plainText += cipher[i];
}
}