작성
·
327
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;
}
이 코드를 실행시키면 아래처럼 나옵니다.. 키 테이블이 문제인데요.. 묶음처리해서 26개 알파벳 모두 넣으려고 하는데 generateKeyTableWithPair()이나
displayKeyTableWithPair()이 문제인가 싶어서 수정해볼려고 하는데도 잘 안돼서요.. 일부러 알파벳 철자 2개를 입력받아서 입력 받은 철자 2개를 묶는걸 의도한건데 어렵게되었어요..
어디가 문제인건지..고쳐주세요..ㅠㅠㅠㅠ
답변 1
0
안녕하세요, 인프런 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 키 테이블을 생성하는 부분이 올바르게 동작할 것입니다.
혹시 해결되지 않는 문제가 있거나 추가적인 도움이 필요한 경우, 인프런의 문의하기를 통해 지원을 요청하실 수도 있습니다.
플레이페어 암호 구현에 성공하시길 바랍니다!