本文展示從教學用簡單 XOR 加密、進階可逆加密,到生產環境標準的 AES-256-GCM 認證加密完整實作,附金鑰管理、IV/Nonce 處理、常見陷阱。
缺陷:無完整性驗證 (可被篡改)、金鑰派生弱 (MD5)、無 IV 導致相同明文產生相同密文、抗暴力破解極弱。
改進:隨機 IV、OpenSSL 標準實作。缺陷:CBC 模式無認證 (Padding Oracle 攻擊)、金鑰派生仍用 MD5。
'sk-xxx', 'secret' => 'ssn-123-45-6789'];
$plaintext = json_encode($data);
$aad = 'user_id:12345|purpose:api_credentials'; // 綁定上下文
try {
$encrypted = ModernCrypto::encrypt($plaintext, $password, $aad);
echo "加密結果: $encrypted\n";
// 存儲 $encrypted 到資料庫...
// 解密 (需相同 password 與 aad)
$decrypted = ModernCrypto::decrypt($encrypted, $password, $aad);
echo "解密結果: $decrypted\n";
print_r(json_decode($decrypted, true));
} catch (Exception $e) {
echo "錯誤: " . $e->getMessage();
}
| 要素 | 錯誤做法 | 正確做法 |
|---|---|---|
| 金鑰來源 | 直接用密碼、MD5(密碼) | PBKDF2/Argon2/Scrypt + 隨機 Salt |
| IV/Nonce | 固定、全零、重複使用 | 每次加密 random_bytes() 產生唯一值 |
| 模式 | ECB、CBC 無認證 | GCM/CCM/OCB (AEAD 認證加密) |
| 完整性 | 無驗證,直接解密 | GCM 自動驗證 Tag,失敗拋出異常 |
| 關聯資料 | 不使用 | AAD 綁定上下文 (用戶 ID、用途、版本) |
| 金鑰輪換 | 永不更換 | 定期輪換,舊資料重新加密或標記版本 |
password_hash($pwd, PASSWORD_ARGON2ID) / PASSWORD_BCRYPT,絕不加密openssl_encrypt/decrypt GCM 支援:PHP 7.1+hash_pbkdf2:PHP 5.5+random_bytes:PHP 7.0+ (5.x 需 paragonie/random_compat)