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

PHP 加密實戰:使用 OpenSSL 實現 DES/AES 對稱加密與解密

     編輯:PHP 相關知識

背景

專案需生成「授權碼」,包含到期時間等敏感資訊,寫入授權文件。客戶端讀取文件,用唯一金鑰解密驗證。早期嘗試 Base64+MD5+反轉等簡易混淆,極易破解。正確做法:採用業界標準對稱加密算法(AES/DES),金鑰管理得當。

對稱加密基礎

算法金鑰長度區塊大小推薦模式備註
AES-256-CBC32 bytes16 bytesCBC/GCM現代首選,硬體加速廣泛支援
AES-128-CBC16 bytes16 bytesCBC/GCM安全性足夠大多數場景
DES-EDE3-CBC (3DES)24 bytes8 bytesCBC已棄用,僅相容舊系統
DES-CBC8 bytes8 bytesCBC極不安全,禁止新專案使用

OpenSSL 實作:AES-256-CBC + PBKDF2 金鑰派生

<?php
class LicenseCrypto {
    private string $cipher = 'AES-256-CBC';
    private int $keyLen;
    private int $ivLen;
    private string $masterKey; // 32 bytes 原始金鑰或高熵密碼

    public function __construct(string $masterKey) {
        $this->keyLen = openssl_cipher_iv_length($this->cipher); // 32
        $this->ivLen  = openssl_cipher_iv_length($this->cipher); // 16
        // 若傳入非 32 bytes,使用 PBKDF2 派生
        $this->masterKey = strlen($masterKey) === $this->keyLen
            ? $masterKey
            : hash_pbkdf2('sha256', $masterKey, '', 200000, $this->keyLen, true);
    }

    /** 生成授權碼(加密) */
    public function encrypt(array $payload): string {
        $plaintext = json_encode($payload, JSON_UNESCAPED_UNICODE);
        $iv = random_bytes($this->ivLen);
        $ciphertext = openssl_encrypt($plaintext, $this->cipher, $this->masterKey, OPENSSL_RAW_DATA, $iv);
        if ($ciphertext === false) {
            throw new \RuntimeException('加密失敗: ' . openssl_error_string());
        }
        // 格式:IV(16) + Ciphertext + HMAC(可選)
        return base64_encode($iv . $ciphertext);
    }

    /** 驗證授權碼(解密) */
    public function decrypt(string $license): array {
        $data = base64_decode($license, true);
        if ($data === false || strlen($data) < $this->ivLen) {
            throw new \InvalidArgumentException('授權碼格式錯誤');
        }
        $iv = substr($data, 0, $this->ivLen);
        $ciphertext = substr($data, $this->ivLen);
        $plaintext = openssl_decrypt($ciphertext, $this->cipher, $this->masterKey, OPENSSL_RAW_DATA, $iv);
        if ($plaintext === false) {
            throw new \RuntimeException('解密失敗:金鑰錯誤或資料已損壞');
        }
        $payload = json_decode($plaintext, true);
        if (!is_array($payload)) {
            throw new \RuntimeException('授權碼內容格式錯誤');
        }
        return $payload;
    }
}

// 使用範例
$crypto = new LicenseCrypto('your-32-byte-master-secret-key-123'); // 實際應從環境變數/密碼管理器讀取

// 生成授權:有效期至 2025-12-31
$license = $crypto->encrypt([
    'product' => 'SuperApp',
    'expires' => '2025-12-31 23:59:59',
    'features' => ['pro', 'api', 'multi-user'],
]);
file_put_contents('/path/to/license.dat', $license);

// 客戶端驗證
try {
    $payload = $crypto->decrypt(file_get_contents('/path/to/license.dat'));
    if (strtotime($payload['expires']) < time()) {
        die('授權已過期');
    }
    echo "授權有效:{$payload['product']} - " . implode(', ', $payload['features']);
} catch (\Throwable $e) {
    die('授權驗證失敗:' . $e->getMessage());
}
?>

進階:AEAD 模式(AES-256-GCM)

PHP 7.1+ 支援 GCM 模式,內建認證標籤(Tag),防範密文竄改:

public function encryptAEAD(array $payload): string {
    $plaintext = json_encode($payload);
    $iv = random_bytes(12); // GCM 建議 12 bytes IV
    $tag = '';
    $ciphertext = openssl_encrypt($plaintext, 'AES-256-GCM', $this->masterKey, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
    // 格式:IV(12) + Tag(16) + Ciphertext
    return base64_encode($iv . $tag . $ciphertext);
}

public function decryptAEAD(string $license): array {
    $data = base64_decode($license, true);
    if (strlen($data) < 28) throw new \InvalidArgumentException('格式錯誤');
    $iv = substr($data, 0, 12);
    $tag = substr($data, 12, 16);
    $ciphertext = substr($data, 28);
    $plaintext = openssl_decrypt($ciphertext, 'AES-256-GCM', $this->masterKey, OPENSSL_RAW_DATA, $iv, $tag);
    // ... 後續同 CBC
}

金鑰管理最佳實踐

  • ✅ 主金鑰絕不硬編碼,使用環境變數、HashiCorp Vault、AWS KMS、AWS Secrets Manager 等。
  • ✅ 不同環境(開發/測試/生產)使用不同金鑰。
  • ✅ 定期輪換金鑰,舊授權碼需提供遷移工具重新加密。
  • ✅ 授權碼增加簽名/認證標籤(HMAC 或 GCM Tag),防止竄改有效期。
  • ❌ 不要使用 ECB 模式(無 IV,相同明文產生相同密文)。
  • ❌ 不要自行設計加密算法或混淆手法。

總結

使用 OpenSSL 的 AES-256-CBC/GCM 搭配 PBKDF2 金鑰派生、隨機 IV、Base64 封裝,能快速構建安全可靠的授權碼系統。核心在於:算法標準化、金鑰與數據分離、完整性驗證、金鑰全生命週期管理。

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