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

PHP 可逆加密解密實用類(基於 Rijndael-256 ECB + Base64URL 安全編碼)

     編輯:PHP 相關知識

在需要「可解密」的場景(如 API Token、配置文件敏感信息、第三方憑證存儲)中,單向哈希(MD5/SHA)不適用。本文提供一個開箱即用的對稱加密類,採用 AES-256 (Rijndael-256) ECB 模式,並處理 Base64 URL 安全編碼。

完整加密解密類

<?php
class Crypt {
    private $skey; // 32 字節二進制密鑰
    
    /**
     * 構造函數:從任意長度字符串派生 256 位密鑰
     * @param string $key 主密鑰(建議 32+ 字符高熵值字符串)
     */
    public function __construct($key) {
        // 使用 MD5 哈希將任意長度密鑰固化為 32 字節(256 位)
        // true 返回原始二進制格式而非十六進制字符串
        $this->skey = hash("md5", $key, true);
    }
    
    /**
     * Base64URL 安全編碼:替換 + / = 為 - _ 空
     * 適用於 URL 參數、Cookie、Header 等場景
     */
    public function safe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+', '/', '='), array('-', '_', ''), $data);
        return $data;
    }
    
    /**
     * Base64URL 安全解碼:還原 - _ 為 + / 並補齊 =
     */
    public function safe_b64decode($string) {
        $data = str_replace(array('-', '_'), array('+', '/'), $string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4); // 補齊 padding
        }
        return base64_decode($data);
    }
    
    /**
     * 加密
     * @param string $value 明文
     * @return string|false 密文(Base64URL)或失敗 false
     */
    public function encode($value) {
        if (!$value) return false;
        
        $text = $value;
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); // ECB 模式 IV 不使用但必須提供
        
        $crypttext = mcrypt_encrypt(
            MCRYPT_RIJNDAEL_256, 
            $this->skey, 
            $text, 
            MCRYPT_MODE_ECB, 
            $iv
        );
        
        return trim($this->safe_b64encode($crypttext));
    }
    
    /**
     * 解密
     * @param string $value 密文(Base64URL)
     * @return string|false 明文或失敗 false
     */
    public function decode($value) {
        if (!$value) return false;
        
        $crypttext = $this->safe_b64decode($value);
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        
        $decrypttext = mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256, 
            $this->skey, 
            $crypttext, 
            MCRYPT_MODE_ECB, 
            $iv
        );
        
        return trim($decrypttext);
    }
}
?>

使用示例

<?php
require_once 'Crypt.php';

// 初始化(生產環境從配置文件/環境變量讀取)
$crypt = new Crypt('your-super-secret-master-key-2024!@#');

// 加密
$plaintext = '{"user_id":12345,"role":"admin","exp":1735689600}';
$ciphertext = $crypt->encode($plaintext);
echo "加密結果: $ciphertext\n";
// 輸出類似: a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6

// 解密
$decrypted = $crypt->decode($ciphertext);
echo "解密結果: $decrypted\n";
// 輸出: {"user_id":12345,"role":"admin","exp":1735689600}

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

關鍵技術細節解析

組件選型說明
加密算法Rijndael-256 (AES-256)區塊大小 256 位,密鑰 256 位,安全性高
加密模式ECB (Electronic Codebook)⚠️ 不安全:相同明文塊產生相同密文塊,無 IV 隨機性
密鑰派生MD5($master_key)固定 32 字節,無 Salt、無迭代,抗暴力破解弱
IV 生成mcrypt_create_iv(RAND)ECB 模式忽略 IV,此處僅滿足 API 要求
編碼輸出Base64URL (RFC 4648 §5)URL 安全,無 + / =,適合 Token 傳輸
填充方式mcrypt 默認 Zero Padding解密後 trim() 移除,若明文含尾部空格會丟失

⚠️ 重大安全警示與現代化替代方案

mcrypt 擴展自 PHP 7.1 棄用,7.2 移除,8.0+ 完全不可用。
本類僅供歷史代碼維護參考,新項目嚴禁使用。

現代標準實現(OpenSSL + PBKDF2 + GCM 模式)

<?php
class ModernCrypt {
    private $key; // 32 字節原始密鑰
    
    public function __construct($master_key, $salt = '') {
        // 使用 PBKDF2 派生密鑰(含 Salt、高迭代次數)
        $this->key = hash_pbkdf2('sha256', $master_key, $salt ?: random_bytes(16), 100000, 32, true);
    }
    
    public function encrypt($plaintext, $associated_data = '') {
        $iv = random_bytes(12); // GCM 建議 96 位 IV
        $ciphertext = openssl_encrypt(
            $plaintext,
            'aes-256-gcm',       // AES-256 GCM 模式(認證加密)
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,                // 認證標籤
            $associated_data     // AAD:關聯數據(如用戶 ID、時間戳)
        );
        // 組合:IV (12) + Tag (16) + Ciphertext
        return $this->safe_b64encode($iv . $tag . $ciphertext);
    }
    
    public function decrypt($ciphertext_b64, $associated_data = '') {
        $data = $this->safe_b64decode($ciphertext_b64);
        if (strlen($data) < 28) return false; // IV(12)+Tag(16) 最小長度
        
        $iv = substr($data, 0, 12);
        $tag = substr($data, 12, 16);
        $ciphertext = substr($data, 28);
        
        return openssl_decrypt(
            $ciphertext,
            'aes-256-gcm',
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            $associated_data
        );
    }
    
    // 同前文 safe_b64encode/decode 方法...
}
?>

遷移檢查清單

  • [ ] 替換 mcrypt 為 openssl_encrypt/decrypt
  • [ ] 算法升級:Rijndael-256-ECB → AES-256-GCM
  • [ ] 密鑰派生:MD5 → PBKDF2/Argon2id(含 Salt、高迭代)
  • [ ] 添加認證加密(GCM 自帶)防範密文篡改
  • [ ] 密鑰管理:環境變量/密鑰管理系統(KMS),不硬編碼
  • [ ] 審計日誌:記錄加解密操作(不記錄明文/密鑰)

加密是系統安全的基石,選擇正確的庫、模式、密鑰管理方式,比實現算法本身更關鍵。

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