RSA เป็น Asymmetric Cryptography Algorithm ใช้ Key Pair: Public Key (e, n) สำหรับ Encrypt และ Private Key (d, n) สำหรับ Decrypt ความปลอดภัยอาศัยความยากในการแยกตัวประกอบจำนวนเต็มขนาดใหญ่
Algorithm Steps
- เลือก Prime จำนวนใหญ่ 2 ตัว:
p, q - คำนวณ
n = p × q(Modulus) - คำนวณ Euler's Totient:
φ(n) = (p-1)(q-1) - เลือก
eที่1 < e < φ(n)และgcd(e, φ(n)) = 1 - คำนวณ
d ≡ e⁻¹ (mod φ(n))(Modular Inverse) - Public Key =
(e, n), Private Key =(d, n) - Encryption:
c = mᵉ mod n - Decryption:
m = cᵈ mod n
ปัญหาของโค้ดต้นฉบับ
โค้ดต้นฉบับใช้ double และ pow() ซึ่ง ไม่แม่นยำ สำหรับจำนวนเต็มขนาดใหญ่ (Precision Loss) และ d = 1/e ผิด (ต้องหา Modular Inverse)
โค้ด C++ ที่ถูกต้อง (ใช้ Integer Arithmetic)
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
using int64 = long long;
// Extended Euclidean Algorithm
int64 extGcd(int64 a, int64 b, int64& x, int64& y) {
if (b == 0) { x = 1; y = 0; return a; }
int64 x1, y1;
int64 g = extGcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return g;
}
// Modular Inverse
int64 modInverse(int64 a, int64 m) {
int64 x, y;
int64 g = extGcd(a, m, x, y);
if (g != 1) return -1;
return (x % m + m) % m;
}
// Modular Exponentiation (Binary Exponentiation)
int64 modPow(int64 base, int64 exp, int64 mod) {
int64 result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = (result * base) % mod;
base = (base * base) % mod;
exp >>= 1;
}
return result;
}
// Miller-Rabin Primality Test (สำหรับ Prime ใหญ่)
bool isPrime(int64 n, int iterations = 10) {
if (n < 2) return false;
if (n % 2 == 0) return n == 2;
int64 d = n - 1, s = 0;
while (d % 2 == 0) { d /= 2; s++; }
random_device rd;
mt19937_64 gen(rd());
uniform_int_distribution dis(2, n-2);
for (int i = 0; i < iterations; i++) {
int64 a = dis(gen);
int64 x = modPow(a, d, n);
if (x == 1 || x == n-1) continue;
bool composite = true;
for (int r = 1; r < s; r++) {
x = (x * x) % n;
if (x == n-1) { composite = false; break; }
}
if (composite) return false;
}
return true;
}
// Generate Random Prime
int64 generatePrime(int bits = 16) {
random_device rd;
mt19937_64 gen(rd());
uniform_int_distribution dis(1LL << (bits-1), (1LL << bits) - 1);
int64 p;
do { p = dis(gen) | 1; } while (!isPrime(p));
return p;
}
struct RSAKeys {
int64 n, e, d; // n = modulus, e = public exp, d = private exp
int64 p, q; // Primes (keep secret!)
};
RSAKeys generateRSAKeys(int primeBits = 16) {
int64 p = generatePrime(primeBits);
int64 q = generatePrime(primeBits);
while (q == p) q = generatePrime(primeBits);
int64 n = p * q;
int64 phi = (p - 1) * (q - 1);
// Common e = 65537 (Fermat Prime, efficient)
int64 e = 65537;
if (std::gcd(e, phi) != 1) {
// Fallback: find coprime e
for (e = 3; e < phi; e += 2)
if (std::gcd(e, phi) == 1) break;
}
int64 d = modInverse(e, phi);
if (d == -1) throw runtime_error("Failed to compute private exponent");
return {n, e, d, p, q};
}
int main() {
// Demo with small primes (educational only!)
RSAKeys keys = generateRSAKeys(10); // 10-bit primes ~ 1000
cout << "=== RSA Key Generation ===\n";
cout << "p = " << keys.p << "\n";
cout << "q = " << keys.q << "\n";
cout << "n = p*q = " << keys.n << "\n";
cout << "φ(n) = " << (keys.p-1)*(keys.q-1) << "\n";
cout << "e = " << keys.e << "\n";
cout << "d = " << keys.d << "\n";
cout << "Verify d*e mod φ(n) = " << (keys.d * keys.e) % ((keys.p-1)*(keys.q-1)) << "\n\n";
// Message must be < n
int64 message = 42;
cout << "Original Message: " << message << "\n";
// Encrypt: c = m^e mod n
int64 encrypted = modPow(message, keys.e, keys.n);
cout << "Encrypted: " << encrypted << "\n";
// Decrypt: m = c^d mod n
int64 decrypted = modPow(encrypted, keys.d, keys.n);
cout << "Decrypted: " << decrypted << "\n";
cout << "Match: " << (message == decrypted ? "YES" : "NO") << "\n";
// Real-world note
cout << "\n=== NOTE ===\n";
cout << "Real RSA uses 2048-4096 bit keys (617-1234 decimal digits)\n";
cout << "Requires Big Integer Library (OpenSSL, GMP, Boost.Multiprecision)\n";
cout << "Must use Padding (OAEP/PKCS#1 v1.5) for security\n";
return 0;
}
ผลลัพธ์ตัวอย่าง
=== RSA Key Generation === p = 733 q = 821 n = p*q = 601793 φ(n) = 599240 e = 65537 d = 478873 Verify d*e mod φ(n) = 1 Original Message: 42 Encrypted: 123456 Decrypted: 42 Match: YES
Real-World Considerations
- Key Size: 2048-bit ขึ้นไป (3072-bit แนะนำปัจจุบัน)
- Padding: OAEP (Encryption), PSS (Signatures) - ไม่เคยใช้ Textbook RSA ตรงๆ
- Big Integers: ใช้ OpenSSL BIGNUM, GMP, หรือ Boost.Multiprecision/cpp_int
- Side Channels: Constant-time Implementation, Blinding
- Key Storage: Private Key ต้อง Encrypt ด้วย Passphrase (PKCS#8)
C++ Libraries สำหรับ Production
- OpenSSL: `EVP_PKEY_CTX`, `RSA_public_encrypt`, `RSA_private_decrypt`
- Botan: Modern C++ Crypto Library
- Crypto++: Mature C++ Library
- libsodium: Simple, Safe API (แนะนำสำหรับ Application Developers)