mcrypt 自 PHP 7.2 棄用、PHP 8.0 移除。新專案請改用 OpenSSL (openssl_encrypt/decrypt) 或 Sodium (libsodium)。本文僅供維護舊系統參考。
php.ini 啟用 extension=php_mcrypt.dll,確認 libmcrypt.dll 在 PATH 中apt-get install php-mcrypt / yum install php-mcrypt → phpenmod mcrypt<?php
print_r(mcrypt_list_algorithms());
print_r(mcrypt_list_modes());
常用組合:
| 演算法常數 | 說明 | 金鑰長度 | 區塊大小 |
|---|---|---|---|
MCRYPT_RIJNDAEL_128 | AES (標準) | 16/24/32 位元組 | 16 位元組 |
MCRYPT_RIJNDAEL_256 | Rijndael-256 (非 AES) | 16/24/32 | 32 |
MCRYPT_TRIPLEDES | 3DES | 24 | 8 |
MCRYPT_BLOWFISH | Blowfish | 4-56 | 8 |
常用模式:
MCRYPT_MODE_CBC(推薦,需 IV)MCRYPT_MODE_ECB(不需 IV,不安全,僅相容舊系統)MCRYPT_MODE_CFB、OFB、CTR(串流模式)$ivSize = mcrypt_get_iv_size($cipher, $mode);
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM); // 加密級隨機
$ciphertext = mcrypt_encrypt($cipher, $key, $plaintext, $mode, $iv);
$plaintext = mcrypt_decrypt($cipher, $key, $ciphertext, $mode, $iv);
<?php
class AesCrypt
{
private const CIPHER = MCRYPT_RIJNDAEL_128; // AES
private const MODE = MCRYPT_MODE_CBC;
private const KEYLEN = 32; // 256-bit
/** 衍生固定長度金鑰(PBKDF2 建議) */
public static function deriveKey(string $password, string $salt): string
{
return hash_pbkdf2('sha256', $password, $salt, 100000, self::KEYLEN, true);
}
/** 加密 → Base64(IV + Ciphertext) */
public static function encrypt(string $data, string $key): string
{
$ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
$pad = self::pkcs7Pad($data, mcrypt_get_block_size(self::CIPHER, self::MODE));
$ct = mcrypt_encrypt(self::CIPHER, $key, $pad, self::MODE, $iv);
return base64_encode($iv . $ct);
}
/** 解密 ← Base64(IV + Ciphertext) */
public static function decrypt(string $b64, string $key): string
{
$raw = base64_decode($b64, true);
if ($raw === false) throw new Exception('Base64 解碼失敗');
$ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
$iv = substr($raw, 0, $ivSize);
$ct = substr($raw, $ivSize);
$pad = mcrypt_decrypt(self::CIPHER, $key, $ct, self::MODE, $iv);
return self::pkcs7Unpad($pad);
}
private static function pkcs7Pad(string $data, int $block): string
{
$pad = $block - (strlen($data) % $block);
return $data . str_repeat(chr($pad), $pad);
}
private static function pkcs7Unpad(string $data): string
{
$pad = ord($data[strlen($data) - 1]);
if ($pad < 1 || $pad > 16) throw new Exception('Padding 驗證失敗');
return substr($data, 0, -$pad);
}
}
// ---- 使用 ----
$pwd = 'user_password_123';
$salt = random_bytes(16);
$key = AesCrypt::deriveKey($pwd, $salt);
$plain = '機密資料:信用卡 4242-4242-4242-4242';
$enc = AesCrypt::encrypt($plain, $key);
$dec = AesCrypt::decrypt($enc, $key);
echo "加密:$enc\n";
echo "解密:$dec\n";
echo "Salt (儲存):" . base64_encode($salt) . "\n";
function opensslAesEncrypt(string $data, string $key): string
{
$iv = random_bytes(16);
$ct = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $ct);
}
function opensslAesDecrypt(string $b64, string $key): string
{
$raw = base64_decode($b64, true);
$iv = substr($raw, 0, 16);
$ct = substr($raw, 16);
return openssl_decrypt($ct, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
}
version | salt | iv | ciphertext | tag 方便日後升級演算法mcrypt 曾是 PHP 加密主力,但已走入歷史。維護舊系統時請嚴謹處理 IV、Padding、金鑰管理;新專案請直接採用 OpenSSL 或 Sodium,獲得更好的安全性、效能與長期支援。