現代 API 介面常需「資料加密傳輸」與「簽名驗證防篡改」。PHP 原生 OpenSSL 操作繁瑣,phpseclib 提供純 PHP 實現的 AES、RSA、大整數運算,無需擴充套件,相容性極佳。本文示範完整流程:AES-ECB 解密資料 → RSA-PKCS1 驗證簽名 → RSA 加解密示範。
composer require phpseclib/phpseclib:~3.0
<?php
require_once 'vendor/autoload.php';
use phpseclib\Crypt\AES;
use phpseclib\Crypt\RSA;
// ========== 1. 參數設定(實際專案請從安全儲存讀取) ==========
// Base64 編碼的 AES 金鑰(16/24/32 位元組對應 128/192/256 bits)
$aesKeyB64 = 'qZe60QZFxuirub2ey4+7+Q==';
$aesKey = base64_decode($aesKeyB64);
// Base64 編碼的 RSA 公鑰(PKCS#1 或 PKCS#8 格式)
$publicKeyB64 = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCffOeIVYut9jW5w1L5uKX4aDvd837a8JhaWm5S8YqNQfgEmfD9T+rDknXLqMT+DXeQAqGo4hBmcbej1aoMzn6hIJHk3/TfTAToNN8fgwDotHewsTCBbVkQWtDTby3GouWToVsRi1i/A0Vfb0+xM8MnF46DdhhrnZrycERBSbyrcwIDAQAB';
$publicKey = base64_decode($publicKeyB64);
// 接收到的加密資料(Base64)
$cryptTextB64 = 'v66YKULHFld2JElhm/J9qik2Edr1JHdZIc/k/OesU2GbTX2usXyvF4jGvzvoihrrE8FsfKmllmjsMIjO5fdrS/FD20bYFii4JW3BO3bzshXmz6AEs2DWwG4sK9mNojfOC0IsMoV311X5/JlgUoQXkDy4F5HHpYE9d/xGb0g2XE/hnGSSy2cpQcvQtBlBmixwSckNhsEG92lovlOz8ULwkqG5o7x+qB7P/EMII/WaFAXBJXDXvZX7lmGcOgon6wLhKJLGXorP6BIxOg6LGc6Ux7BAt3i9+0lujNgxIq/sDsl23hsr3yOUpV5C5a813nrHx4HJyd/hBT1UvIUml+eTmJwWCpSfs2cvxIUr0CE57JAZVyXjK13shK3IsZHLPPsm/JcDCrdy0Co/d5uIGJAdzXdsQ56xsju+tlvnA1J6yq2tDIfYK/x6k911A5WXLKYxztD1nq+bTYN3Gv/WFfrzVtgWQBrh06ihS2cwvna0S9EV/YPmhnAjJmrX4trNr9NXQ9xaZaW4lGRg87U5QDV+nQjj1THk0XHFc69N9g2+DsAGyEs9tK6U0ZQ72hJZqZhBCDH1UKw0PLyIhJdxpgPPOWGp8/QVVU2julTeKunvgAAEc3n+GoZfqjsCDi1S6T2MTnjWYWNoFRBhvEZFD/revgpasTOzDQa5NqR1B+mUF70r6uw6MWLJ7cT9Tz3jq+CA';
$cryptText = base64_decode($cryptTextB64);
// 接收到的簽名(Base64)
$signatureB64 = 'XHin4uUFqrKDEhKBD/hQisXLFFSxM6EZCvCPqnWCQJq3uEp3ayxmFuUgVE0Xoh4AIWjIIsOWdnaToL1bXvAFKwjCtXnkaRwUpvWrk+Q0eqwsoAdywsVQDEceG5stas1CkPtrznAIW2eBGXCWspOj+aumEAcPyYDxLhDN646Krzw=';
$signature = base64_decode($signatureB64);
// ========== 2. AES-ECB 解密 ==========
$aes = new AES(AES::MODE_ECB);
$aes->setKey($aesKey);
$plainText = $aes->decrypt($cryptText);
echo "解密後明文:\n$plainText\n
";
// ========== 3. RSA-PKCS1 驗證簽名 ==========
$rsa = new RSA();
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); // 或 SIGNATURE_PSS(更安全)
$rsa->loadKey($publicKey); // 載入公鑰
$verified = $rsa->verify($plainText, $signature);
echo "簽名驗證:" . ($verified ? '✅ 通過' : '❌ 失敗') . "\n
";
// ========== 4. RSA 加解密示範(生成新鑰對) ==========
$keys = $rsa->createKey(2048); // 產生 2048-bit 鑰對
$privateKey = $keys['privatekey'];
$publicKeyNew = $keys['publickey'];
// 使用私鑰加密(通常用於小資料加密或金鑰交換)
$rsa->loadKey($privateKey);
$cipherText = $rsa->encrypt($plainText);
echo "RSA 私鑰加密結果(Base64):\n" . base64_encode($cipherText) . "\n
";
// 使用公鑰解密
$rsa->loadKey($publicKeyNew);
$decrypted = $rsa->decrypt($cipherText);
echo "RSA 公鑰解密還原:\n$decrypted\n";
?>
| 類別 | 常用模式常數 | 說明 |
|---|---|---|
AES | MODE_ECB, MODE_CBC, MODE_CTR, MODE_GCM | ECB 不需 IV 但不安全(相同明文產生相同密文),生產環境強制使用 CBC/GCM 並搭配隨機 IV |
RSA | SIGNATURE_PKCS1, SIGNATURE_PSS | PSS 比 PKCS1 更安全,建議新專案用 PSS。加密模式:ENCRYPTION_PKCS1, ENCRYPTION_OAEP(OAEP 更安全) |
MODE_CBC + 隨機 IV(AES::generateIV()),IV 需與密文一起傳輸(通常前綴在密文前)。RSA::SIGNATURE_PSS + SHA256($rsa->setHash('sha256'))。hash_equals() 或 phpseclib 內建的恆時比較。
<?php
// AES-256-GCM(推薦)
$key = random_bytes(32);
$iv = random_bytes(12); // GCM 建議 96-bit IV
$ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
// 儲存:$iv . $ciphertext . $tag
// 解密
$plaintext = openssl_decrypt($ciphertext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
// RSA 簽名驗證(PSS + SHA256)
openssl_sign($data, $signature, $privateKey, 'sha256WithRSAEncryption'); // 需開啟 OPENSSL_ALGO_SHA256
$ok = openssl_verify($data, $signature, $publicKey, 'sha256WithRSAEncryption');
?>
phpseclib 在無法安裝擴充套件的共享主機環境極有價值;若掌控伺服器環境,優先使用內建 OpenSSL,效能更好、經過更嚴格審計。