仿射密码解密,输出大小写不同
Posted
技术标签:
【中文标题】仿射密码解密,输出大小写不同【英文标题】:Affine cipher decryption, output differs for upper case and lower case 【发布时间】:2020-02-03 12:44:00 【问题描述】:我在使用仿射密码解密明文时遇到问题。 加密工作正常,但对小写/大写字符的解密应用相同的逻辑会返回不同的输出。
这是输出:
加密消息是:ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD 解密消息为: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;
【问题讨论】:
将((((a * (plainText[i]-'a') ) + b) % 26) + 'a')
更改为(((((a * (plainText[i]-'a') ) + b) % 26) + 'a') % 26)
每次出现a
和b
变量都是编译器错误。你的意思是'a'
和'b'
?
... 例如,在这一行中:cipher = cipher + (char) ((((a * (plainText[i]-'A') ) + b) % 26) + 'A');
您使用 a
和 b
- 但这些声明和/或定义在哪里?
@AdrianMole a 和 b 是仿射密码的密钥。以下公式 E ( x ) = ( a x + b ) mod m 和 D ( x ) = a^-1 ( x - b ) mod m
然后请在您发布的代码中包含这些定义! (我试图编译您的代码以查看问题出在哪里,但由于错误而无法编译 - 这就是为什么我们要求一个最小的 reproducible 示例!!)
【参考方案1】:
我一直在考虑这个问题,虽然我无法提供完整的解释,但我有一些可能有用的“观察”,以及一个“作弊”解决方法.
首先,尽管您说您使用“相同的逻辑来解密小写/大写”,每个解密块中的代码的字符对齐表明这是' t 相当是的:
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];
【讨论】:
以上是关于仿射密码解密,输出大小写不同的主要内容,如果未能解决你的问题,请参考以下文章