Vigenère Cipher là mật mã thay thế đa bảng (polyalphabetic) — cải tiến của Caesar Cipher bằng cách dùng khóa lặp lại để xác định độ dịch chuyển khác nhau cho từng vị trí.
Nguyên lý
- Khóa
Klặp lại để khớp độ dài bản rõP. - Mã hóa:
C[i] = (P[i] + K[i]) mod 26 - Giải mã:
P[i] = (C[i] - K[i] + 26) mod 26 - Chỉ xử lý chữ cái A-Z/a-z, bỏ qua ký tự khác.
Bảng Vigenère (Tabula Recta)
Ma trận 26x26 các hàng Caesar Cipher dịch chuyển lần lượt 0..25. Hàng = bản rõ, cột = khóa, giao = bản mã.
Chương trình hoàn chỉnh (OOP)
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
class Vigenere {
string key; // Khóa đã chuẩn hóa (chỉ A-Z)
public:
Vigenere(string k) {
for (char ch : k) {
if (isupper(ch)) key += ch;
else if (islower(ch)) key += toupper(ch);
}
}
string encrypt(const string& plaintext) {
string cipher;
for (size_t i = 0, j = 0; i < plaintext.size(); ++i) {
char ch = plaintext[i];
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
int p = ch - base;
int k = key[j % key.size()] - 'A';
int c = (p + k) % 26;
cipher += char(base + c);
++j; // Chỉ tăng chỉ số khóa khi xử lý chữ cái
} else {
cipher += ch; // Giữ nguyên ký tự khác
}
}
return cipher;
}
string decrypt(const string& ciphertext) {
string plain;
for (size_t i = 0, j = 0; i < ciphertext.size(); ++i) {
char ch = ciphertext[i];
if (isalpha(ch)) {
char base = isupper(ch) ? 'A' : 'a';
int c = ch - base;
int k = key[j % key.size()] - 'A';
int p = (c - k + 26) % 26;
plain += char(base + p);
++j;
} else {
plain += ch;
}
}
return plain;
}
};
int main() {
Vigenere cipher("WELCOME");
string original = "This is TutorialsPoint";
string encrypted = cipher.encrypt(original);
string decrypted = cipher.decrypt(encrypted);
cout << "Ban ro: " << original << '\n';
cout << "Ban ma: " << encrypted << '\n';
cout << "Giai ma: " << decrypted << '\n';
return 0;
}
Kết quả
Ban ro: This is TutorialsPoint Ban ma: Pltu Wex Qxztwm Potzkbf Giai ma: This is TutorialsPoint
Lưu ý: Kết quả có thể khác ví dụ gốc do xử lý khoảng trắng và case-insensitive key.
Phân tích bảo mật
- Không gian khóa:
26^LvớiLđộ dài khóa (rất lớn nếu khóa dài). - Kháng cự phân tích tần suất đơn biến — nhưng vẫn yếu trước Kasiski examination và Friedman test (xác định độ dài khóa).
- An toàn nếu khóa: ngẫu nhiên, dài ≥ bản rõ, chỉ dùng một lần (One-Time Pad).
So sánh với Caesar & Affine
| Mật mã | Loại | Khóa | Độ an toàn |
|---|---|---|---|
| Caesar | Monoalphabetic | 1 số (0-25) | Rất yếu (26 khóa) |
| Affine | Monoalphabetic | 2 số (a,b) | Yếu (312 khóa) |
| Vigenère | Polyalphabetic | Chuỗi ký tự | Trung bình (phụ thuộc độ dài khóa) |
Mẹo triển khai
- Chuẩn hóa khóa: loại bỏ non-alpha, chuyển về uppercase.
- Bảo toàn case của bản rõ (A→A, a→a).
- Bỏ qua ký tự không phải chữ cái (space, punctuation, số) — không tăng chỉ số khóa.
- Dùng
(x + 26) % 26khi trừ để tránh modulo âm trong C++.
Vigenère là bước tiến quan trọng trong lịch sử mật mã học, cầu nối giữa mật mã cổ điển và hiện đại.