inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

C++로 플레이페어 암호를 구현하려고 해요..

350

Tiz

작성한 질문수 2

0

// C++ program for encryption using Playfair Cipher
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

#define SIZE 30

// Function to convert the string to lowercase
void toLowerCase(char plain[], int ps)
{
    for (int i = 0; i < ps; i++)
    {
        if (plain[i] >= 'A' && plain[i] <= 'Z') // 대문자를 소문자로 변환
            plain[i] = tolower(plain[i]);
    }
}

// Function to remove duplicate characters from the key
void removeDuplicates(char key[], int &ks)
{
    int index = 0;

    for (int i = 0; i < ks; ++i)
    {
        int j;
        for (j = 0; j < i; ++j)
        {
            if (key[i] == key[j])
            {
                break;
            }
        }
        if (i == j)
        {
            key[index++] = key[i];
        }
    }

    key[index] = '\0';
    ks = index;
}

// Function to remove all spaces in a string
int removeSpaces(char *plain, int ps)
{
    int count = 0;
    for (int i = 0; i < ps; i++)
    {
        if (plain[i] != ' ')
            plain[count++] = plain[i];
    }
    plain[count] = '\0';
    return count;
}

// Function to generate the 5x5 key square
void generateKeyTable(char key[], int ks, char keyT[5][5])
{
    int i, j, k, *d;

    // a 26 character hashmap to store count of the alphabet
    d = (int *)calloc(26, sizeof(int));
    for (i = 0; i < ks; i++)
    {
        if (key[i] != 'j')
            d[key[i] - 97] = 2;
    }

    d['j' - 97] = 1;

    i = 0;
    j = 0;

    for (k = 0; k < ks; k++)
    {
        if (d[key[k] - 97] == 2)
        {
            d[key[k] - 97] -= 1;
            keyT[i][j] = key[k];
            j++;
            if (j == 5)
            {
                i++;
                j = 0;
            }
        }
    }

    for (k = 0; k < 26; k++)
    {
        if (d[k] == 0)
        {
            keyT[i][j] = (char)(k + 97);
            j++;
            if (j == 5)
            {
                i++;
                j = 0;
            }
        }
    }
}

// Function to search for the characters of a digraph
// in the key square and return their position
void search(char keyT[5][5], char a, char b, int arr[])
{
    int i, j;

    if (a == 'j')
        a = 'i';
    else if (b == 'j')
        b = 'i';

    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
            if (keyT[i][j] == a)
            {
                arr[0] = i;
                arr[1] = j;
            }
            else if (keyT[i][j] == b)
            {
                arr[2] = i;
                arr[3] = j;
            }
        }
    }
}

// Function to find the modulus with 5
int mod5(int a)
{
    return (a % 5);
}

// Function to make the plain text length to be even
int prepare(char str[], int ptrs)
{
    if (ptrs % 2 != 0)
    {
        str[ptrs++] = 'z';
        str[ptrs] = '\0';
    }
    return ptrs;
}

// Function for performing the encryption
void encrypt(char str[], char keyT[5][5], int ps)
{
    int i, a[4];

    for (i = 0; i < ps; i += 2)
    {
        search(keyT, str[i], str[i + 1], a);

        if (a[0] == a[2])
        {
            str[i] = keyT[a[0]][mod5(a[1] + 1)];
            str[i + 1] = keyT[a[0]][mod5(a[3] + 1)];
        }
        else if (a[1] == a[3])
        {
            str[i] = keyT[mod5(a[0] + 1)][a[1]];
            str[i + 1] = keyT[mod5(a[2] + 1)][a[1]];
        }
        else
        {
            str[i] = keyT[a[0]][a[3]];
            str[i + 1] = keyT[a[2]][a[1]];
        }
    }
}

void preparePlainText(char txt[], string mEncryption)
{
    int cnt = 0;

    mEncryption.erase(remove(mEncryption.begin(), mEncryption.end(), ' '), mEncryption.end());
    cout << "\n공백 제거 후: " << mEncryption << endl;

    char txt2[2 * SIZE];
    strcpy(txt2, mEncryption.c_str());

    cnt = 0;
    int len = strlen(txt2);

    for (int i = 0; i < len; i += 2){
        if (txt2[i] == txt2[i + 1])
        {
            txt[cnt++] = txt2[i];
            txt[cnt++] = 'x';
        }
        else
        {
            txt[cnt++] = txt2[i];
            txt[cnt++] = txt2[i + 1];
        }
    }
    len = strlen(txt);

    if (len % 2 == 1)
    {
        txt[len] = 'x';
        txt[len + 1] = '\0';
    }
    cout << "X 붙이고 자른 후: ";

    for (int i = 0; txt[i] != 0; i++)
    {
        cout << txt[i];

        if (i % 2 == 1)
        {
            cout << " ";
        }
    }
}

// Function to display the 5x5 key table including paired characters
void displayKeyTableWithPair(char keyT[5][5], char pair1, char pair2)
{
    cout << "\n5x5 Key Table:" << endl;
    for (int i = 0; i < 5; ++i)
    {
        for (int j = 0; j < 5; ++j)
        {
            if (keyT[i][j] == pair1)
            {
                cout << pair1 << "/" << pair2 << "\t";
            }
            else if (keyT[i][j] == pair2)
            {
                // To avoid duplicate display when pair1 == pair2
                if (pair1 != pair2)
                {
                    continue;
                }
                cout << pair1 << "/" << pair2 << "\t";
            }
            else
            {
                cout << keyT[i][j] << "\t";
            }
        }
        cout << endl;
    }
}

// Function to encrypt using Playfair Cipher
void encryptByPlayfairCipher(char str[], char key[])
{
    int ps, ks;
    char keyT[5][5];

    ks = strlen(key);
    ks = removeSpaces(key, ks);
    toLowerCase(key, ks);
    ps = strlen(str);
    toLowerCase(str, ps);
    ps = removeSpaces(str, ps);
    ps = prepare(str, ps);
    generateKeyTable(key, ks, keyT);
    encrypt(str, keyT, ps);
}

void generateKeyTableWithPair(char key[], int ks, char keyT[5][5], char pair1, char pair2)
{
    int i, j, k, *d;

    // a 26 character hashmap to store count of the alphabet
    d = (int *)calloc(26, sizeof(int));

    for (i = 0; i < ks; i++)
    {
        if (key[i] != 'j')
            d[key[i] - 97] = 2;
    }

    d['j' - 97] = 1;
    i = 0;
    j = 0;

    bool addedPair1 = false,
    addedPair2 = false;

    for (k = 0; k < ks; k++)
    {
        if (d[key[k] - 97] == 2)
        {
            d[key[k] - 97] -= 1;
            keyT[i][j] = key[k];
            j++;
            if (j == 5)
            {
                i++;
                j = 0;
            }
        }
    }

    // Additional loop to accommodate remaining characters
    for (k = 0; k < 26; k++)
    {
        if (d[k] == 0)
        {
            if (key[k] == pair1 && !addedPair1)
            {
                keyT[i][j++] = pair1;
                keyT[i][j++] = pair2;
                addedPair1 = true;
            }
            else if (key[k] == pair2 && !addedPair2)
            {
                keyT[i][j++] = pair2;
                keyT[i][j++] = pair1;
                addedPair2 = true;
            }
            else if (key[k] != pair1 && key[k] != pair2)
            {
                keyT[i][j++] = (char)(k + 97);
            }
            if (j == 5)
            {
                i++;
                j = 0;
            }
        }
    }
}

int main()
{
    char str[SIZE], key[SIZE];

    cout << "키 값 입력 ↓ " << endl;
    cin.getline(key, SIZE);
    int ks = strlen(key);
    removeDuplicates(key, ks);
    cout << "중복 제거된 키 값 -> " << key << endl;

    // Additional input for two characters
    char pair1, pair2;
    cout << "\n알파벳 2개 입력: ";
    cin >> pair1 >> pair2;

    cout << "\n평문 입력 ↓ " << endl;
    cin.ignore(); // Clear input buffer
    cin.getline(str, SIZE);

    cout << "\n";
    cout << "입력된 키 값 -> " << key << endl;
    cout << "입력된 평문 ->  " << str << endl;

    // Generate the 5x5 key table with pair1 and pair2 included
    char keyT[5][5];
    generateKeyTableWithPair(key, ks, keyT, pair1, pair2);
    // Display the 5x5 key table including paired characters
    displayKeyTableWithPair(keyT, pair1, pair2);

    // Prepare the plaintext and pair characters
    char txt[2 * SIZE];
    string plaintext(str);
    preparePlainText(txt, plaintext);

    encryptByPlayfairCipher(str, key);
    cout << "\n"
        << endl;
    cout << "암호문 : " << str << endl;

    return 0;
}

스크린샷 2023-12-08 오전 12.48.43.png이 코드를 실행시키면 아래처럼 나옵니다.. 키 테이블이 문제인데요.. 묶음처리해서 26개 알파벳 모두 넣으려고 하는데 generateKeyTableWithPair()이나

displayKeyTableWithPair()이 문제인가 싶어서 수정해볼려고 하는데도 잘 안돼서요.. 일부러 알파벳 철자 2개를 입력받아서 입력 받은 철자 2개를 묶는걸 의도한건데 어렵게되었어요..

어디가 문제인건지..고쳐주세요..ㅠㅠㅠㅠ

답변 1

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.
Tiz님, C++로 플레이페어 암호를 구현하는 데 어려움을 겪고 계시군요. 코드와 설명을 바탕으로 문제가 발생하는 부분을 짚어 드리겠습니다.

먼저, generateKeyTableWithPair() 함수에서 키 테이블을 구성할 때 if (key[k] == pair1 && !addedPair1) 조건에서 key[k] 대신 k + 'a' 또는 char(k + 97)를 사용해야 합니다. 현재 코드에서는 key[k]를 사용하고 있는데, 이는 입력 키 문자열에서 k번째 문자를 나타내므로 알파벳 문자를 확인하는 것이 아닙니다.

generateKeyTableWithPair() 함수 내에서 다음과 같이 코드를 수정해 보세요:

// ... 이전 코드 생략 ...

for (k = 0; k < 26; k++) {
    // key[k] 대신 (char)(k + 97)를 사용하여 알파벳을 확인합니다.
    if (d[k] == 0) {
        char currentChar = (char)(k + 97);
        if (currentChar == pair1 && !addedPair1) {
            keyT[i][j++] = pair1;
            keyT[i][j++] = pair2;
            addedPair1 = true;
        }
        else if (currentChar == pair2 && !addedPair2) {
            keyT[i][j++] = pair2;
            keyT[i][j++] = pair1;
            addedPair2 = true;
        }
        else if (currentChar != pair1 && currentChar != pair2) {
            keyT[i][j++] = currentChar;
        }
        if (j == 5) {
            i++;
            j = 0;
        }
    }
}

// ... 이후 코드 생략 ...

또한, 아스키코드 값 ‘j’가 97가 아닌 106임을 고려해야 합니다.

이와 같이 코드를 변경한 후 다시 실행하면, 입력한 두 문자를 묶어 5x5 키 테이블을 생성하는 부분이 올바르게 동작할 것입니다.

혹시 해결되지 않는 문제가 있거나 추가적인 도움이 필요한 경우, 인프런의 문의하기를 통해 지원을 요청하실 수도 있습니다.

플레이페어 암호 구현에 성공하시길 바랍니다!

강의 수강 후 포트폴리오 준비 방향에 대해 조언 부탁드립니다.

2

47

1

시스템 아키텍처를 강의에 나온 것 처럼 그리고 싶은데 공유 가능할까요?

1

48

2

포트폴리오에 대한 질문이 있습니다!

1

45

2

7회 3유형 2번문제 질문

1

27

2