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

PHP 可逆加密解密類實作(基於 AES-256-ECB)

     編輯:PHP 綜合知識

用戶密碼儲存應使用單向雜湊(如 bcrypt/Argon2),但某些業務場景(API Token、第三方憑證、配置文件敏感值)需可逆加密。本文提供一個基於 OpenSSL AES-256-ECB 的加解密類,含 URL 安全 Base64 編碼、金鑰派生、異常處理。

核心類別實作

<?php
class Crypt {
    private string $key; // 32 位元組二進制金鑰

    public function __construct(string $secret) {
        // 使用 SHA-256 將任意長度密鑰派生為 32 字節
        $this->key = hash('sha256', $secret, true);
    }

    /** URL 安全 Base64 編碼(移除 + / =) */
    private function safeB64Encode(string $data): string {
        $b64 = base64_encode($data);
        return str_replace(['+', '/', '='], ['-', '_', ''], $b64);
    }

    /** URL 安全 Base64 解碼(自動補齊 =) */
    private function safeB64Decode(string $data): string {
        $b64 = str_replace(['-', '_'], ['+', '/'], $data);
        $mod4 = strlen($b64) % 4;
        if ($mod4) {
            $b64 .= substr('====', $mod4);
        }
        return base64_decode($b64);
    }

    /** 加密:返回 URL 安全字串 */
    public function encrypt(string $value): ?string {
        if ($value === '') return null;
        // AES-256-ECB 不需 IV,但 OpenSSL 要求提供,傳空字串
        $ciphertext = openssl_encrypt($value, 'AES-256-ECB', $this->key, OPENSSL_RAW_DATA);
        if ($ciphertext === false) {
            throw new RuntimeException('加密失敗: ' . openssl_error_string());
        }
        return $this->safeB64Encode($ciphertext);
    }

    /** 解密:返回原始明文 */
    public function decrypt(string $value): ?string {
        if ($value === '') return null;
        $ciphertext = $this->safeB64Decode($value);
        $plaintext = openssl_decrypt($ciphertext, 'AES-256-ECB', $this->key, OPENSSL_RAW_DATA);
        if ($plaintext === false) {
            throw new RuntimeException('解密失敗: ' . openssl_error_string());
        }
        return $plaintext;
    }
}

使用範例

$crypt = new Crypt('my-super-secret-key-2024'); // 實際應從環境變數讀取

$original = 'sk_live_abcdef1234567890'; // 敏感 API Key
$encrypted = $crypt->encrypt($original);
echo "加密: $encrypted\n";

$decrypted = $crypt->decrypt($encrypted);
echo "解密: $decrypted\n";
// 驗證
var_dump($original === $decrypted); // true

安全性說明與改進建議

項目現狀建議
模式ECB (Electronic Codebook)生產環境強烈建議改用 CBC 或 GCM 模式,ECB 模式相同明文塊產生相同密文塊,洩漏模式特徵
IV (初始化向量)ECB 不使用CBC/GCM 需為每次加密生成隨機 IV (16 字節),並與密文一起儲存(如 IV + 密文)
金鑰管理硬編碼/配置文件使用環境變數、HashiCorp Vault、AWS KMS 等密鑰管理系統
完整性驗證無GCM 模式內建認證標籤;CBC 需額外 HMAC (Encrypt-then-MAC)
密鑰輪換不支援在密文前加版本號,支援多版本金鑰並行解密、平滑遷移

改進版:AES-256-GCM(推薦 PHP 7.1+)

public function encryptGCM(string $value): string {
    $iv = random_bytes(16); // GCM 建議 12 字節,16 也可
    $tag = '';
    $ciphertext = openssl_encrypt($value, 'AES-256-GCM', $this->key, OPENSSL_RAW_DATA, $iv, $tag);
    // 儲存格式: IV (16) + TAG (16) + CIPHERTEXT
    return $this->safeB64Encode($iv . $tag . $ciphertext);
}

public function decryptGCM(string $value): string {
    $data = $this->safeB64Decode($value);
    $iv = substr($data, 0, 16);
    $tag = substr($data, 16, 16);
    $ciphertext = substr($data, 32);
    $plaintext = openssl_decrypt($ciphertext, 'AES-256-GCM', $this->key, OPENSSL_RAW_DATA, $iv, $tag);
    if ($plaintext === false) throw new RuntimeException('GCM 解密失敗/資料被竄改');
    return $plaintext;
}

結論:本類適合快速原型、內部工具、非極高安全場景。處理支付憑證、個人身份信息等敏感數據時,請務必使用 GCM 模式並妥善管理金鑰。

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