Расшифровка аффинного шифра, выходные данные различаются для верхнего и нижнего регистра - PullRequest
1 голос
/ 03 февраля 2020

У меня проблема при расшифровке открытого текста с использованием шифра Affine. Шифрование работает нормально, но применение одного и того же логика c для дешифрования символов нижнего и верхнего регистра возвращает различный вывод.

Вот вывод:

Зашифрованное сообщение: ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD
Дешифрованное сообщение: opqrstuvwxyzabcdefghijklmn YSCB * * * Может кто-нибудь поправить меня?

Вот мой код:

#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; 
} 


1 Ответ

0 голосов
/ 03 февраля 2020

Я некоторое время думал об этом, и, хотя я не могу дать полное объяснение, у меня есть пара «наблюдений», которые могут быть полезны, плюс обходной путь «обмана».

Во-первых, хотя вы говорите, что используете "тот же лог 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];
    }
}
...