Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 구현하는 아핀 암호(Affine Cipher): 원리부터 코드까지


아핀 암호(Affine Cipher)는 알파벳의 각 문자를 숫자 값에 매핑하는 단일 치환 암호(monoalphabetic substitution cipher)의 한 종류입니다. 암호화는 간단한 수학 함수를 통해 이루어지며, 그 결과는 다시 문자로 변환됩니다.

아핀 암호에서는 크기가 m인 알파벳의 문자들이 먼저 0부터 m-1까지의 정수 범위에 매핑됩니다.

아핀 암호의 '키(key)'는 a와 b라는 두 개의 숫자로 구성되며, 이때 a는 반드시 m과 서로소(relatively prime) 관계여야 합니다.

암호화(Encryption)

암호화 과정에서는 모듈러 산술(modular arithmetic)을 사용하여 각 평문(plaintext) 문자에 해당하는 정수를, 암호문(ciphertext) 문자에 대응하는 다른 정수로 변환합니다. 단일 문자에 대한 암호화 함수는 다음과 같습니다.

E ( x ) = ( a x + b ) mod m
modulus m: 알파벳의 크기
a와 b: 암호의 키

복호화(Decryption)

복호화 과정에서는 각 암호문 문자를 해당하는 정수 값으로 변환합니다. 복호화 함수는 다음과 같습니다.

D ( x ) = a^-1 ( x - b ) mod m
a^-1 : a modulo m의 모듈러 곱셈 역원(modular multiplicative inverse). 즉, 다음 방정식을 만족합니다.
1 = a^-1 mod m

다음은 이 과정을 구현한 C++ 프로그램입니다.

알고리즘

시작
함수 encryption(string m)
    i = 0부터 m.length()-1까지 반복
        if(m[i]!=' ')
            c = c + (char) ((((a * (m[i]-'A') ) + b) % 26) + 'A')
        else
            c += m[i]
    return c
종료
시작
함수 decryption(string c)
    a_inverse = 0으로 초기화
    flag = 0으로 초기화
    i = 0부터 25까지 반복
        flag = (a * i) % 26
        if (flag == 1)
            a_inverse = i
        반복 끝
    반복 끝
    i = 0부터 c.length() - 1까지 반복
        if(c[i]!=' ')
            m = m + (char) (((a_inverse * ((c[i]+'A' - b)) % 26)) + 'A')
        else
            m = m + c[i]
    반복 끝
종료

예제 코드

#include<bits/stdc++.h>
using namespace std;
static int a = 7;
static int b = 6;
string encryption(string m) {
    // 암호문을 처음에는 빈 문자열로 초기화
    string c = "";
    for (int i = 0; i < m.length(); i++) {
        // 공백 문자는 암호화하지 않고 건너뜀
        if(m[i]!=' ')
            // 'A'를 더해 ASCII 알파벳 범위 [ 65-90 | A-Z ]로 조정
            c = c + (char) ((((a * (m[i]-'A') ) + b) % 26) + 'A');
        else
            // 그 외의 경우 공백 문자를 그대로 추가
            c += m[i];
    }
    return c;
}
string decryption(string c) {
    string m = "";
    int a_inverse = 0;
    int flag = 0;
    // a^-1 (모듈로 m 정수군에서 a의 곱셈 역원)을 구함
    for (int i = 0; i < 26; i++) {
        flag = (a * i) % 26;
        // (a * i) % 26 == 1이면,
        // i가 a의 곱셈 역원이 됨
        if (flag == 1) {
            a_inverse = i;
        }
    }
    for (int i = 0; i < c.length(); i++) {
        if(c[i] != ' ')
            // 'A'를 더해 ASCII 알파벳 범위 [ 65-90 | A-Z ]로 조정
            m = m + (char) (((a_inverse * ((c[i]+'A' - b)) % 26)) + 'A');
        else
            // 그 외의 경우 공백 문자를 그대로 추가
            m += c[i];
    }
    return m;
}
int main(void) {
    string msg = "TUTORIALSPOINT";
    string c = encryption(msg);
    cout << "Encrypted Message is : " << c<<endl;
    cout << "Decrypted Message is: " << decryption(c);
    return 0;
}

실행 결과

Encrypted Message is : JQJAVKGFCHAKTJ
Decrypted Message is: TUTORIALSPOINT