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