在 Ubuntu 上部署 PHP 應用 (特別是舊版 Laravel、Magento 等) 時,常遇到 PHP Warning: PHP Startup: Unable to load dynamic library 'mcrypt' 錯誤。自 PHP 7.2 起,mcrypt 已從核心移除並棄用 (改用 OpenSSL/Sodium),但舊專案可能仍有相依。
sudo apt-get update
sudo apt-get install php5-mcrypt # PHP 5.x
# 或
sudo apt-get install php7.1-mcrypt # PHP 7.1 (需加入 ondrej/php PPA)
# PHP 5.x / 7.0-7.1 (mod_php 或 php-fpm)
sudo php5enmod mcrypt # PHP 5
sudo phpenmod mcrypt # PHP 7.0+
# 重啟 Web 伺服器 / PHP-FPM
sudo systemctl restart apache2
# 或
sudo systemctl restart php7.1-fpm
php -m | grep mcrypt
# 應顯示 mcrypt
mcrypt 已棄用且移除**,請勿嘗試在 PHP 7.2+ 強行安裝 (相容性極差)。應改用以下原生擴展:
| 原 mcrypt 用途 | 現代替代方案 | PHP 版本 |
|---|---|---|
| AES/DES/3DES 加密 | openssl_encrypt() / openssl_decrypt() | 5.3+ |
| 亂數產生 | random_bytes() / random_int() | 7.0+ |
| 密碼雜湊 | password_hash() / password_verify() | 5.5+ |
| 高階加密 (AEAD, XChaCha20-Poly1305) | sodium_* 函式庫 (libsodium) | 7.2+ (核心內建) |
<?php
// 舊寫法 (mcrypt)
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
// 新寫法 (OpenSSL) - AES-256-CBC
$encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
// 新寫法 (Sodium) - XChaCha20-Poly1305 (推薦,需 PHP 7.2+)
$key = sodium_crypto_aead_xchacha20poly1305_ietf_keygen();
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
$encrypted = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($data, '', $nonce, $key);
$decrypted = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($encrypted, '', $nonce, $key);
| 問題 | 原因 | 解決 |
|---|---|---|
MCRYPT_RIJNDAEL_128 ≠ AES-128 | Rijndael 支援區塊大小 128/192/256,AES 固定 128 | 遷移時確認區塊大小,AES 使用 AES-128/192/256-CBC |
| 金鑰長度不符 | mcrypt 自動填充/截斷金鑰,OpenSSL 嚴格檢查 | AES-256 需 32 位元組金鑰,使用 hash('sha256', $key, true) 衍生 |
| IV 長度 | CBC 模式 IV 必須等於區塊大小 (AES 16 位元組) | random_bytes(16) 產生 |
| 資料填充 | mcrypt 預設 Zero Padding,OpenSSL 預設 PKCS#7 | 指定 OPENSSL_ZERO_PADDING 或統一 PKCS#7 |
# Dockerfile (PHP 7.1 為例)
FROM php:7.1-apache
RUN apt-get update && apt-get install -y libmcrypt-dev \
&& docker-php-ext-install mcrypt pdo_mysql
對於 PHP 7.1 及以下舊專案,安裝 php-mcrypt 並啟用模組即可解決。但**強烈建議**規劃遷移至 OpenSSL/Sodium 原生函式,這不僅解決相容性問題,更能獲得現代密碼學的安全性能優勢 (AEAD、抗邊緣通道攻擊、硬體加速)。新專案請直接使用 sodium_* 或 openssl_* 函式庫。