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

PHP AES 加密類別實作(基於 mcrypt 擴展)與現代替代方案

     編輯:PHP 相關知識

本文提供一個基於 mcrypt 擴展的 AES 加密/解密類別 AESMcrypt,支援多種金鑰長度(128/192/256 位元)與模式(CBC/ECB/CFB/OFB/NOFB)。注意:mcrypt 已於 PHP 7.1 棄用、PHP 7.2 移除,新專案請改用 openssl_encrypt() / openssl_decrypt()。

AESMcrypt 類別代碼

<?php
class AESMcrypt {
    public $iv = null;
    public $key = null;
    public $bit = 128;
    private $cipher;
    private $mode;

    public function __construct($bit, $key, $iv, $mode) {
        if (empty($bit) || empty($key) || empty($iv) || empty($mode)) {
            return null;
        }
        $this->bit = $bit;
        $this->key = $key;
        $this->iv = $iv;
        $this->mode = $mode;

        // 映射金鑰長度至 mcrypt 常數
        switch ($this->bit) {
            case 192: $this->cipher = MCRYPT_RIJNDAEL_192; break;
            case 256: $this->cipher = MCRYPT_RIJNDAEL_256; break;
            default:  $this->cipher = MCRYPT_RIJNDAEL_128;
        }

        // 映射模式至 mcrypt 常數
        switch (strtolower($this->mode)) {
            case 'ecb': $this->mode = MCRYPT_MODE_ECB; break;
            case 'cfb': $this->mode = MCRYPT_MODE_CFB; break;
            case 'ofb': $this->mode = MCRYPT_MODE_OFB; break;
            case 'nofb': $this->mode = MCRYPT_MODE_NOFB; break;
            default:    $this->mode = MCRYPT_MODE_CBC;
        }
    }

    // 加密:輸出 Base64 編碼字串
    public function encrypt($data) {
        $encrypted = mcrypt_encrypt($this->cipher, $this->key, $data, $this->mode, $this->iv);
        return base64_encode($encrypted);
    }

    // 解密:移除 PKCS#7 padding(mcrypt 使用零填充,需自行處理)
    public function decrypt($data) {
        $decrypted = mcrypt_decrypt($this->cipher, $this->key, base64_decode($data), $this->mode, $this->iv);
        // 移除填充(null 字元與控制字元)
        return rtrim(rtrim($decrypted), "\x00..\x1F");
    }
}
?>

使用範例

<?php
// 參數:金鑰長度、金鑰(16/24/32 位元組)、IV(16 位元組)、模式
$aes = new AESMcrypt(
    $bit = 128,
    $key = 'abcdef1234567890',      // 16 bytes = 128 bits
    $iv  = '0987654321fedcba',      // 16 bytes
    $mode = 'cbc'
);

$plaintext = 'haowei.me';
$ciphertext = $aes->encrypt($plaintext);
echo "加密: $ciphertext<br>";

$decrypted = $aes->decrypt($ciphertext);
echo "解密: $decrypted<br>";

// 驗證
var_dump($plaintext === $decrypted); // bool(true)
?>

重要安全提醒

  • 金鑰管理:勿硬編碼金鑰於程式碼,應從環境變數、金鑰管理系統(KMS)或設定檔(排除版控)讀取。
  • IV 唯一性:CBC 模式下,每次加密應使用隨機 IV,並將 IV 與密文一起儲存(IV 不需保密)。
  • 填充模式:mcrypt 使用零填充,可能導致資料尾端為 \x00 時解密錯誤。建議自行實作 PKCS#7 填充。
  • 完整性驗證:純加密無法防範密文竄改,生產環境應使用 Authenticated Encryption(如 AES-GCM 或 encrypt-then-MAC)。

現代替代方案:OpenSSL (PHP 7.1+)

推薦使用內建 openssl_encrypt(),支援 AES-GCM(自帶認證):

<?php
function aesGcmEncrypt(string $data, string $key, string &$iv, string &$tag): string {
    $iv = random_bytes(12); // GCM 建議 12 位元組 IV
    $ciphertext = openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
    return base64_encode($ciphertext);
}

function aesGcmDecrypt(string $ciphertextB64, string $key, string $iv, string $tag): string|false {
    $ciphertext = base64_decode($ciphertextB64);
    return openssl_decrypt($ciphertext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
}

// 使用
$key = random_bytes(32); // 256-bit 金鑰
$plaintext = '敏感資料';
$ciphertext = aesGcmEncrypt($plaintext, $key, $iv, $tag);
// 儲存:$ciphertext, $iv, $tag
$decrypted = aesGcmDecrypt($ciphertext, $key, $iv, $tag);
?>

總結比較

特性mcrypt (AESMcrypt)OpenSSL (AES-GCM)
PHP 版本支援< 7.2>= 7.1
認證加密無(需自行實作 MAC)內建 (GCM/CCM)
效能較慢硬體加速、較快
維護狀態已移除積極維護

結論:舊專案維護可暫用 AESMcrypt,但應規劃遷移至 OpenSSL AES-GCM 以確保安全性與相容性。

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