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

PHP 加密解密工具類實現:基於對稱加密的數據安全方案

     編輯:PHP 相關知識

設計目標

提供一個簡單、可復用的 PHP 加密解密類,滿足以下需求:

  • 敏感數據存儲加密(如 API Key、用戶隱私字段)
  • URL 參數傳輸加密(防篡改、防洩露)
  • 配置文件敏感信息保護
  • 無需擴展依賴,純 PHP 實現

核心類實現

<?php
/**
 * SysCrypt - 對稱加密工具類
 * 算法特點:基於隨機密鑰流的 XOR 加密 + Base64 編碼 + 主鑰二次混淆
 * 適用場景:中短文本加密、配置保護、參數簽名
 * 不適用場景:大文件加密、高安全等級需求(請使用 OpenSSL AES-256-GCM)
 */
class SysCrypt {
    private string $cryptKey;

    public function __construct(string $cryptKey) {
        if (empty($cryptKey)) {
            throw new InvalidArgumentException('加密主鑰不能為空');
        }
        $this->cryptKey = $cryptKey;
    }

    /**
     * 加密文本
     * @param string $plaintext 明文
     * @return string Base64 編碼的密文
     */
    public function encrypt(string $plaintext): string {
        // 1. 生成隨機會話鑰 (16字節足夠)
        $sessionKey = bin2hex(random_bytes(16)); // 32字符十六進制
        
        // 2. 明文與會話鑰 XOR 混淆 (交織模式)
        $obfuscated = '';
        $keyLen = strlen($sessionKey);
        for ($i = 0; $i < strlen($plaintext); $i++) {
            $obfuscated .= $sessionKey[$i % $keyLen] . ($plaintext[$i] ^ $sessionKey[$i % $keyLen]);
        }
        
        // 3. 主鑰二次加密
        $encrypted = $this->xorWithKey($obfuscated, $this->cryptKey);
        
        // 4. Base64 編碼便於傳輸存儲
        return base64_encode($encrypted);
    }

    /**
     * 解密文本
     * @param string $ciphertext Base64 編碼密文
     * @return string 明文
     * @throws Exception 解密失敗
     */
    public function decrypt(string $ciphertext): string {
        // 1. Base64 解碼
        $decoded = base64_decode($ciphertext, true);
        if ($decoded === false) {
            throw new Exception('無效的 Base64 密文');
        }
        
        // 2. 主鑰解密
        $obfuscated = $this->xorWithKey($decoded, $this->cryptKey);
        
        // 3. 還原明文 (跳過會話鑰字符)
        $plaintext = '';
        for ($i = 0; $i < strlen($obfuscated); $i += 2) {
            // $obfuscated[$i] 是會話鑰字符,跳過
            if (isset($obfuscated[$i + 1])) {
                $plaintext .= $obfuscated[$i + 1] ^ $obfuscated[$i];
            }
        }
        
        return $plaintext;
    }

    /**
     * 核心 XOR 混淆算法
     */
    private function xorWithKey(string $data, string $key): string {
        $keyHash = md5($key); // 固定 32 字符
        $result = '';
        $keyLen = strlen($keyHash);
        
        for ($i = 0; $i < strlen($data); $i++) {
            $result .= $data[$i] ^ $keyHash[$i % $keyLen];
        }
        return $result;
    }

    /**
     * 靜態快捷方法
     */
    public static function quickEncrypt(string $data, string $key): string {
        return (new self($key))->encrypt($data);
    }

    public static function quickDecrypt(string $data, string $key): string {
        return (new self($key))->decrypt($data);
    }
}

// ===== 使用示例 =====
$crypt = new SysCrypt('MySecretKey2024!@#'); // 生產環境請從環境變量讀取

$original = 'user_id=10086&api_key=sk_live_xxx×tamp=' . time();
echo "原文: $original\n";

$encrypted = $crypt->encrypt($original);
echo "密文: $encrypted\n";

$decrypted = $crypt->decrypt($encrypted);
echo "解密: $decrypted\n";

echo "驗證: " . ($original === $decrypted ? '通過 ✓' : '失敗 ✗') . "\n";
?>

安全性分析與改進建議

層面現狀風險改進方案
算法強度自定義 XOR 流加密抗密文分析能力弱,不抗已知明文攻擊生產環境改用 openssl_encrypt($data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag)
密鑰管理硬編碼/構造函數傳入代碼洩露導致密鑰洩露使用環境變量、密鑰管理服務(Vault)、HSM
完整性驗證無密文可被篡改解密出垃圾數據添加 HMAC-SHA256 簽名或使用 AEAD 模式 (GCM/CCM)
重放攻擊無防護同一密文可重複使用在明文中包含時間戳/Nonce,解密後驗證時效性
隨機性random_bytes() CSPRNG會話鑰生成安全保持現狀

生產級替代方案:OpenSSL AES-256-GCM

<?php
class ModernCrypt {
    private string $key; // 32 字節 (256 bit)
    private int $ivLen = 12; // GCM 推薦 12 字節 IV
    private int $tagLen = 16; // 認證標籤 16 字節

    public function __construct(string $keyBase64) {
        $this->key = base64_decode($keyBase64);
        if (strlen($this->key) !== 32) {
            throw new InvalidArgumentException('密鑰必須為 32 字節 Base64 編碼');
        }
    }

    public function encrypt(string $plaintext, string $associatedData = ''): string {
        $iv = random_bytes($this->ivLen);
        $tag = '';
        $ciphertext = openssl_encrypt(
            $plaintext,
            'AES-256-GCM',
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            $associatedData
        );
        if ($ciphertext === false) {
            throw new Exception('加密失敗: ' . openssl_error_string());
        }
        // 組合: IV(12) + Ciphertext + Tag(16) -> Base64
        return base64_encode($iv . $ciphertext . $tag);
    }

    public function decrypt(string $ciphertextB64, string $associatedData = ''): string {
        $data = base64_decode($ciphertextB64, true);
        if ($data === false || strlen($data) < $this->ivLen + $this->tagLen) {
            throw new Exception('無效密文格式');
        }
        
        $iv = substr($data, 0, $this->ivLen);
        $tag = substr($data, -$this->tagLen);
        $ciphertext = substr($data, $this->ivLen, -$this->tagLen);
        
        $plaintext = openssl_decrypt(
            $ciphertext,
            'AES-256-GCM',
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            $associatedData
        );
        if ($plaintext === false) {
            throw new Exception('解密失敗/數據被篡改: ' . openssl_error_string());
        }
        return $plaintext;
    }
}

// 生成密鑰 (僅執行一次,安全保存)
$key = base64_encode(random_bytes(32));
echo "請妥善保存此密鑰: $key\n";

// 使用
$crypt = new ModernCrypt($key);
$data = '{"user_id":10086,"role":"admin","exp":' . (time()+3600) . '}';
$enc = $crypt->encrypt($data, 'api_v1'); // 關聯數據綁定上下文
echo "加密: $enc\n";
echo "解密: " . $crypt->decrypt($enc, 'api_v1') . "\n";
?>

常見應用場景代碼片段

1. 配置文件敏感字段加密

<?php
// config.encrypted.php
return [
    'database' => [
        'host' => 'localhost',
        'password' => 'ENC:eyJpdiI6I...', // 加密後的密碼
    ],
    'redis' => [
        'password' => 'ENC:abc123...',
    ],
];

// 運行時解密
function decryptConfig(array $config, ModernCrypt $crypt): array {
    array_walk_recursive($config, function(&$value) use ($crypt) {
        if (is_string($value) && str_starts_with($value, 'ENC:')) {
            $value = $crypt->decrypt(substr($value, 4));
        }
    });
    return $config;
}
?>

2. URL 安全參數傳遞

<?php
function signUrl(string $route, array $params, ModernCrypt $crypt, int $ttl = 3600): string {
    $params['_ts'] = time();
    $params['_exp'] = time() + $ttl;
    $payload = http_build_query($params);
    $encrypted = $crypt->encrypt($payload);
    return $route . '?token=' . urlencode($encrypted);
}

function verifyUrlToken(string $token, ModernCrypt $crypt): ?array {
    try {
        $payload = $crypt->decrypt(urldecode($token));
        parse_str($payload, $params);
        if (($params['_exp'] ?? 0) < time()) {
            return null; // 過期
        }
        unset($params['_ts'], $params['_exp']);
        return $params;
    } catch (Exception) {
        return null; // 篡改或無效
    }
}

// 生成帶簽名的下載鏈接
$url = signUrl('/download', ['file_id' => 123, 'user_id' => 456], $crypt, 1800);
// 輸出: /download?token=eyJpdiI6I...

// 驗證
$params = verifyUrlToken($_GET['token'] ?? '', $crypt);
if ($params) {
    // 允許下載 $params['file_id']
}
?>

總結

  • 學習/內部工具:本文的 SysCrypt 類結構清晰,適合理解對稱加密原理
  • 生產環境:務必使用 ModernCrypt (AES-256-GCM),提供機密性、完整性、認證性三重保障
  • 密鑰管理:永不硬編碼,使用環境變量、KMS、Vault 等專業方案
  • 合規性:涉及個人隱私/支付數據請遵循 GDPR、PCI-DSS、等保 2.0 等標準

加密只是資安拼圖的一塊,還需結合 HTTPS 傳輸、最小權限原則、審計日誌、入侵檢測等纵深防禦體系。

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