Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

C++ Program: Implement Affine Cipher (Affine Cipher)


Affine Cipher เป็น Monoalphabetic Substitution Cipher ที่แปลงตัวอักษรแต่ละตัวด้วยฟังก์ชันคณิตศาสตร์แบบ Linear Modular Arithmetic

Mathematical Foundation

Alphabet Size m = 26 (A-Z)

Key: (a, b) โดย a ต้อง Coprime กับ m (gcd(a, 26) = 1) เพื่อให้มี Inverse

Encryption

E(x) = (a * x + b) mod 26

Decryption

D(y) = a⁻¹ * (y - b) mod 26

ที่ a⁻¹ คือ Modular Multiplicative Inverse: a * a⁻¹ ≡ 1 (mod 26)

Valid Keys (a values)

a ต้อง Coprime กับ 26 → a ∈ {1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25} (12 ค่า)

b ∈ [0, 25] (26 ค่า) → Total Keys = 12 × 26 = 312

โค้ด C++ สมบูรณ์

#include <bits/stdc++.h>
using namespace std;

class AffineCipher {
    int a, b, a_inv;
    const int M = 26;
    
    // Extended Euclidean Algorithm หา Modular Inverse
    int modInverse(int a, int m) {
        a = ((a % m) + m) % m;
        for (int x = 1; x < m; x++)
            if ((a * x) % m == 1) return x;
        return -1; // No inverse
    }
    
public:
    AffineCipher(int a_, int b_) : a(a_), b(b_) {
        a_inv = modInverse(a, M);
        if (a_inv == -1) 
            throw invalid_argument("Key 'a' must be coprime with 26");
    }
    
    string encrypt(const string& plaintext) {
        string ciphertext;
        for (char ch : plaintext) {
            if (isalpha(ch)) {
                char base = isupper(ch) ? 'A' : 'a';
                int x = ch - base;
                int y = (a * x + b) % M;
                ciphertext += char(y + base);
            } else {
                ciphertext += ch; // Preserve non-alphabetic
            }
        }
        return ciphertext;
    }
    
    string decrypt(const string& ciphertext) {
        string plaintext;
        for (char ch : ciphertext) {
            if (isalpha(ch)) {
                char base = isupper(ch) ? 'A' : 'a';
                int y = ch - base;
                int x = (a_inv * (y - b + M)) % M; // +M ป้องกัน Negative
                plaintext += char(x + base);
            } else {
                plaintext += ch;
            }
        }
        return plaintext;
    }
};

int main() {
    // Key: a=7, b=6 (7 coprime กับ 26, inverse = 15)
    AffineCipher cipher(7, 6);
    
    string msg = "TUTORIALSPOINT";
    string encrypted = cipher.encrypt(msg);
    string decrypted = cipher.decrypt(encrypted);
    
    cout << "Original:  " << msg << '\n';
    cout << "Encrypted: " << encrypted << '\n';
    cout << "Decrypted: " << decrypted << '\n';
    
    // Test with spaces and lowercase
    string msg2 = "Hello World!";
    cout << "\nOriginal:  " << msg2 << '\n';
    cout << "Encrypted: " << cipher.encrypt(msg2) << '\n';
    cout << "Decrypted: " << cipher.decrypt(cipher.encrypt(msg2)) << '\n';
    
    return 0;
}

ผลลัพธ์

Original:  TUTORIALSPOINT
Encrypted: JQJAVKGFCHAKTJ
Decrypted: TUTORIALSPOINT

Original:  Hello World!
Encrypted: Pmttw Ewztl!
Decrypted: Hello World!

Security Analysis

  • Key Space: เพียง 312 Keys → Brute Force ได้ง่ายมาก
  • Frequency Analysis: เป็น Monoalphabetic → รูปแบบความถี่คงอยู่
  • Known Plaintext Attack: ถ้ารู้ Plaintext-Ciphertext คู่เดียว หา Key ได้
  • ไม่ปลอดภัย สำหรับการใช้งานจริง ใช้ AES แทน

การหา Modular Inverse แบบ Extended Euclid (เร็วกว่า)

int extGcd(int a, int b, int& x, int& y) {
    if (b == 0) { x = 1; y = 0; return a; }
    int x1, y1;
    int g = extGcd(b, a % b, x1, y1);
    x = y1;
    y = x1 - (a / b) * y1;
    return g;
}

int modInverse(int a, int m) {
    int x, y;
    int g = extGcd(a, m, x, y);
    if (g != 1) return -1;
    return (x % m + m) % m;
}