Я некоторое время думал об этом, и, хотя я не могу дать полное объяснение, у меня есть пара «наблюдений», которые могут быть полезны, плюс обходной путь «обмана».
Во-первых, хотя вы говорите, что используете "тот же лог c для расшифровки строчных и прописных букв" посимвольное выравнивание кода из каждого из ваших блоков расшифровки показывает, что это не вполне истина:
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];
}
}