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

PHP mcrypt 擴充完整指南:安裝、演算法、模式與 AES 加解密實戰

     編輯:PHP 綜合知識

重要提醒

mcrypt 自 PHP 7.2 棄用、PHP 8.0 移除。新專案請改用 OpenSSL (openssl_encrypt/decrypt) 或 Sodium (libsodium)。本文僅供維護舊系統參考。

安裝與啟用

  1. Windows:php.ini 啟用 extension=php_mcrypt.dll,確認 libmcrypt.dll 在 PATH 中
  2. Linux:apt-get install php-mcrypt / yum install php-mcrypt → phpenmod mcrypt
  3. 重啟 Web 伺服器 / PHP-FPM

支援的演算法與模式

<?php
print_r(mcrypt_list_algorithms());
print_r(mcrypt_list_modes());

常用組合:

演算法常數說明金鑰長度區塊大小
MCRYPT_RIJNDAEL_128AES (標準)16/24/32 位元組16 位元組
MCRYPT_RIJNDAEL_256Rijndael-256 (非 AES)16/24/3232
MCRYPT_TRIPLEDES3DES248
MCRYPT_BLOWFISHBlowfish4-568

常用模式:

  • 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);

完整 AES-256-CBC 範例(含 PKCS#7 Padding)

<?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";

遷移至 OpenSSL(PHP 7.1+ 推薦)

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);
}
  • OpenSSL 內建 PKCS#7 padding,無需手動處理
  • 支援 AES-GCM(認證加密,防篡改)
  • 效能優於 mcrypt,且持續維護

安全最佳實務

  1. 永不硬編碼金鑰:使用環境變數、密碼管理系統(HashiCorp Vault、AWS KMS)
  2. 每次加密產生新 IV:IV 不需保密,但必須唯一且不可預測
  3. 金鑰衍生用 PBKDF2 / Argon2:不要直接用密碼當金鑰
  4. 認證加密 (AEAD):優先選 AES-GCM 或 ChaCha20-Poly1305 (Sodium)
  5. 儲存格式:version | salt | iv | ciphertext | tag 方便日後升級演算法

結語

mcrypt 曾是 PHP 加密主力,但已走入歷史。維護舊系統時請嚴謹處理 IV、Padding、金鑰管理;新專案請直接採用 OpenSSL 或 Sodium,獲得更好的安全性、效能與長期支援。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved