首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Mcrypt 擴充庫加密解密完整教學:AES/RIJNDAEL 範例

     編輯:PHP 相關知識

⚠️ 重要提示

Mcrypt 擴充自 PHP 7.1 棄用、PHP 7.2 移除。現代專案請改用 OpenSSL (openssl_encrypt/decrypt) 或 libsodium (sodium_crypto_secretbox)。本文僅供維護舊專案參考。

Mcrypt 支援演算法 (部分)

  • 區塊加密:MCRYPT_RIJNDAEL_128 (AES)、MCRYPT_RIJNDAEL_192、MCRYPT_RIJNDAEL_256
  • 串流加密:MCRYPT_RC4、MCRYPT_WAKE
  • 其他:MCRYPT_BLOWFISH、MCRYPT_TWOFISH、MCRYPT_DES、MCRYPT_3DES、MCRYPT_SERPENT、MCRYPT_XTEA

模式 (Mode)

完整加密解密範例 (AES-128-CBC)

<?php
// 參數
$plaintext = "機密資料:信用卡號 1234-5678-9012-3456";
$key = "ThisIsASecretKey123456"; // 16/24/32 bytes 對應 128/192/256 bits
$cipher = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_CBC;

// 產生 IV (初始化向量)
$ivSize = mcrypt_get_iv_size($cipher, $mode);
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM); // 安全隨機源

// 加密
$ciphertext = mcrypt_encrypt($cipher, $key, $plaintext, $mode, $iv);
// 通常將 IV + 密文一起儲存/傳輸 (IV 不需保密)
$encoded = base64_encode($iv . $ciphertext);
echo "Encrypted: $encoded\n";

// 解密
$decoded = base64_decode($encoded);
$iv = substr($decoded, 0, $ivSize);
$ciphertext = substr($decoded, $ivSize);
$decrypted = mcrypt_decrypt($cipher, $key, $ciphertext, $mode, $iv);
// 移除 PKCS#7 padding
$decrypted = rtrim($decrypted, "\0");
echo "Decrypted: $decrypted\n";

關鍵安全細節

  1. 金鑰長度:必須精確符合演算法要求 (AES-128=16 bytes、AES-256=32 bytes)
  2. IV 唯一性:CBC 模式下,**每次加密必須使用新的隨機 IV**
  3. IV 儲存:IV 可公開,通常預置在密文前方
  4. Padding:Mcrypt 使用零填充,解密後需 rtrim($data, "\0");OpenSSL 預設 PKCS#7
  5. 金鑰管理:勿硬編碼,使用環境變數、Key Vault、KMS
  6. 認證加密:Mcrypt 無內建認證,建議加密後計算 HMAC (Encrypt-then-MAC)

現代替代:OpenSSL (PHP 5.3+ 內建)

function encrypt(string $data, string $key): string {
    $cipher = 'AES-256-CBC';
    $ivLen = openssl_cipher_iv_length($cipher);
    $iv = random_bytes($ivLen);
    $ct = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv . $ct);
}

function decrypt(string $encoded, string $key): string {
    $cipher = 'AES-256-CBC';
    $data = base64_decode($encoded);
    $ivLen = openssl_cipher_iv_length($cipher);
    $iv = substr($data, 0, $ivLen);
    $ct = substr($data, $ivLen);
    return openssl_decrypt($ct, $cipher, $key, OPENSSL_RAW_DATA, $iv);
}

現代替代:libsodium (PHP 7.2+ 內建、最高安全性)

function encrypt_sodium(string $data, string $key): string {
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $cipher = sodium_crypto_secretbox($data, $nonce, $key);
    return base64_encode($nonce . $cipher);
}

function decrypt_sodium(string $encoded, string $key): string {
    $data = base64_decode($encoded);
    $nonce = substr($data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $cipher = substr($data, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    return sodium_crypto_secretbox_open($cipher, $nonce, $key);
}
// 金鑰需為 SODIUM_CRYPTO_SECRETBOX_KEYBYTES (32 bytes)
$key = sodium_crypto_secretbox_keygen();

遷移清單

常數全名特點
MCRYPT_MODE_ECBElectronic Codebook不需 IV、相同明文產生相同密文 (不安全)
MCRYPT_MODE_CBCCipher Block Chaining需 IV、推薦一般用途
MCRYPT_MODE_CFBCipher Feedback串流模式、需 IV
MCRYPT_MODE_OFBOutput Feedback串流模式、需 IV
MCRYPT_MODE_NOFBOutput Feedback (n-bit)較少用
McryptOpenSSLlibsodium
mcrypt_encryptopenssl_encryptsodium_crypto_secretbox
mcrypt_decryptopenssl_decryptsodium_crypto_secretbox_open
mcrypt_create_ivrandom_bytesrandom_bytes
MCRYPT_RIJNDAEL_128AES-128/256-CBCXChaCha20-Poly1305
零填充PKCS#7 (自動)內建認證加密
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved