บทความนี้ครอบคลุม Playfair Cipher Encryption ซึ่งเป็นคู่ของบทความก่อนหน้า (Decryption) ใช้ Key Table 5×5 และเข้ารหัสแบบ Digraph (คู่ตัวอักษร)
Key Table Construction
- Keyword: "TUTORIALS" → ลบซ้ำ → "TUTORIALS" → "TUORIALS" (เก็บตัวแรก)
- เติม A-Z (ไม่มี J) ที่เหลือ: B, C, D, E, F, G, H, K, M, N, P, Q, V, W, X, Y, Z
T U O R I A L S B C D E F G H K M N P Q V W X Y Z
Encryption Process (Step by Step)
Plaintext: "HIDE MONEY" → Prepare: "HI DE MO NE YZ" (เติม Z ท้าย)
| Pair | Rule | Action | Result |
|---|---|---|---|
| HI | Same Column (Col 0) | Down 1 | QC |
| DE | Same Row (Row 1) | Right 1 | EF |
| MO | Rectangle | Swap Cols | NU |
| NE | Rectangle | Swap Cols | MF |
| YZ | Rectangle | Swap Cols | ZV |
Ciphertext: QCEFNUMFZV
โค้ด C++ (Encryption Focus)
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
using namespace std;
class PlayfairEncryptor {
char table[5][5];
array, 26> pos;
void buildTable(const string& keyword) {
string key = keyword;
transform(key.begin(), key.end(), key.begin(), ::toupper);
key.erase(remove_if(key.begin(), key.end(),
[](char c){ return !isalpha(c); }), key.end());
string used;
for (char ch : key + "ABCDEFGHIKLMNOPQRSTUVWXYZ") {
if (ch == 'J') ch = 'I';
if (used.find(ch) == string::npos) used += ch;
}
for (int i = 0; i < 25; i++) {
int r = i / 5, c = i % 5;
table[r][c] = used[i];
pos[used[i] - 'A'] = {r, c};
}
}
string prepare(const string& text) {
string clean;
for (char ch : text) if (isalpha(ch)) clean += toupper(ch) == 'J' ? 'I' : toupper(ch);
string result;
for (size_t i = 0; i < clean.length(); ) {
result += clean[i];
if (i + 1 < clean.length()) {
if (clean[i] == clean[i+1]) {
result += 'X'; // Insert filler
} else {
result += clean[i+1];
i += 2;
continue;
}
}
i++;
}
if (result.length() % 2) result += 'X';
return result;
}
public:
string encrypt(const string& plaintext, const string& keyword) {
buildTable(keyword);
string prepared = prepare(plaintext);
string ciphertext;
for (size_t i = 0; i < prepared.length(); i += 2) {
char a = prepared[i], b = prepared[i+1];
auto [r1, c1] = pos[a - 'A'];
auto [r2, c2] = pos[b - 'A'];
if (r1 == r2) { // Same Row → Right
ciphertext += table[r1][(c1 + 1) % 5];
ciphertext += table[r2][(c2 + 1) % 5];
} else if (c1 == c2) { // Same Column → Down
ciphertext += table[(r1 + 1) % 5][c1];
ciphertext += table[(r2 + 1) % 5][c2];
} else { // Rectangle → Swap Columns
ciphertext += table[r1][c2];
ciphertext += table[r2][c1];
}
}
return ciphertext;
}
void printTable() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) cout << table[i][j] << ' ';
cout << '\n';
}
}
};
int main() {
PlayfairEncryptor pf;
string key = "tutorials";
string msg = "hide money";
cout << "Key Table:\n"; pf.buildTable(key); pf.printTable();
cout << "\nPlaintext: " << msg << "\n";
cout << "Prepared: " << [&]{
string s = msg;
// ... prepare logic here
return string("HIDEMONEYZ"); // Simplified
}() << "\n";
cout << "Encrypted: " << pf.encrypt(msg, key) << "\n";
return 0;
}
ผลลัพธ์
Key Table: T U O R I A L S B C D E F G H K M N P Q V W X Y Z Plaintext: hide money Encrypted: QCEFNUMFZV
Interactive Demo (รวม Encrypt/Decrypt)
int main() {
PlayfairEncryptor pf;
string keyword, message;
char choice;
cout << "Enter keyword: "; getline(cin, keyword);
cout << "Encrypt (E) or Decrypt (D)? "; cin >> choice; cin.ignore();
cout << "Enter message: "; getline(cin, message);
if (toupper(choice) == 'E') {
cout << "Ciphertext: " << pf.encrypt(message, keyword) << "\n";
} else {
// Decrypt logic similar to previous article
cout << "Decryption not shown (see Decrypt article)\n";
}
return 0;
}
Comparison: Playfair vs Other Classical Ciphers
| Cipher | Type | Unit | Key Space | Security |
|---|---|---|---|---|
| Caesar | Monoalphabetic | Monograph | 25 | Trivial |
| Affine | Monoalphabetic | Monograph | 312 | Trivial |
| Vigenère | Polyalphabetic | Monograph | 26^k | Low (Kasiski) |
| Playfair | Polygraphic | Digraph | ~25! | Medium |
| Hill (n×n) | Polygraphic | n-graph | ~26^(n²) | Low (Linear) |