本類別實作一種以密碼字串產生動態替換表的對稱加密演算法,屬於維吉尼亞密碼 的變體。核心思想:以密碼每字元在基礎字母表中的位置為起點,產生一組位移後的替換字母表,加密時逐字元查表替換,解密則反向查表。密碼長度決定替換表組數,加密過程循環使用。
$ralphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !,.:;?~@#$%^&*()_+-=][}{/><'\"";
$alphabet = $ralphabet . $ralphabet; // 雙倍長度,方便 substr 截取位移後的完整表
class Crypto {
function encrypt($password, $strtoencrypt) {
global $ralphabet, $alphabet;
$pos_alpha_ary = [];
$len_pwd = strlen($password);
// 依密碼字元產生替換表陣列
for ($i = 0; $i < $len_pwd; $i++) {
$cur = substr($password, $i, 1);
$pos_alpha_ary[] = substr(strstr($alphabet, $cur), 0, strlen($ralphabet));
}
$encrypted = '';
$n = 0;
$c = strlen($strtoencrypt);
while ($n < $c) {
$char = substr($strtoencrypt, $n, 1);
$pos = strpos($ralphabet, $char);
if ($pos !== false) {
$encrypted .= substr($pos_alpha_ary[$n % $len_pwd], $pos, 1);
} else {
$encrypted .= $char; // 不在字母表中的字元保持原樣
}
$n++;
}
return $encrypted;
}
function decrypt($password, $strtodecrypt) {
global $ralphabet, $alphabet;
$pos_alpha_ary = [];
$len_pwd = strlen($password);
for ($i = 0; $i < $len_pwd; $i++) {
$cur = substr($password, $i, 1);
$pos_alpha_ary[] = substr(strstr($alphabet, $cur), 0, strlen($ralphabet));
}
$decrypted = '';
$n = 0;
$c = strlen($strtodecrypt);
while ($n < $c) {
$char = substr($strtodecrypt, $n, 1);
$table = $pos_alpha_ary[$n % $len_pwd];
$pos = strpos($table, $char);
if ($pos !== false) {
$decrypted .= substr($ralphabet, $pos, 1);
} else {
$decrypted .= $char;
}
$n++;
}
return $decrypted;
}
// 顯示密表(除錯/教學用)
function cryption_table($password) {
global $ralphabet, $alphabet;
$pos_alpha_ary = [];
for ($i = 0; $i < strlen($password); $i++) {
$cur = substr($password, $i, 1);
$pos_alpha_ary[] = substr(strstr($alphabet, $cur), 0, strlen($ralphabet));
}
echo "";
echo " ";
for ($j = 0; $j < strlen($ralphabet); $j++) echo "" . substr($ralphabet, $j, 1) . " ";
echo " ";
for ($i = 0; $i < count($pos_alpha_ary); $i++) {
echo "" . ($i+1) . "| ";
for ($k = 0; $k < strlen($pos_alpha_ary[$i]); $k++) {
echo "" . substr($pos_alpha_ary[$i], $k, 1) . " ";
}
echo " ";
}
echo "
";
}
}
$ct = new Crypto();
$password = "secret";
$plain = "Hello World 123";
$encrypted = $ct->encrypt($password, $plain);
echo "加密:" . $encrypted . "
";
$decrypted = $ct->decrypt($password, $encrypted);
echo "解密:" . $decrypted . "
";
// 驗證
var_dump($plain === $decrypted); // bool(true)
// 顯示密表
$ct->cryption_table($password);
| 項目 | 評估 |
|---|---|
| 加密強度 | 極低。屬古典密碼學,易受頻率分析、已知明文攻擊破解 |
| 金鑰空間 | 字母表 72 字元,密碼長度 n → 72^n,但實際熵值遠低於現代標準 |
| 完整性 | 無驗證機制,密文可被竄改且解密仍產生合法明文 |
| 支援字元 | 僅限 $ralphabet 定義字元,Unicode/中文/換行符不支援 |
| 適用場景 | 教學示範、極低敏感度資料混淆、CTF 解謎、紙筆加密趣味 |
function aes_encrypt($data, $key, $iv) {
return openssl_encrypt($data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag);
}
function aes_decrypt($data, $key, $iv, $tag) {
return openssl_decrypt($data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag);
}
$key = sodium_crypto_secretbox_keygen();
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher = sodium_crypto_secretbox($message, $nonce, $key);
$plain = sodium_crypto_secretbox_open($cipher, $nonce, $key);
雖不安全,但展示了:替換表生成、模組化循環使用金鑰、字元級對映、對稱加密結構。適合作為密碼學入門教材,理解「為什麼不能自己造加密」的反面教材。