怎样在PHP项目中实现用户自定义加密?

wen java案例 3

本文目录导读:

怎样在PHP项目中实现用户自定义加密?

  1. 基础用户自定义加密(对称加密)
  2. 多用户加密管理系统
  3. 用户自定义加密算法选择器
  4. 数据库配置存储方案
  5. 完整示例:完整的用户加密系统
  6. 安全建议

在PHP项目中实现用户自定义加密功能,需要根据不同的需求场景选择合适的方案,以下是几种常见的实现方式,从简单到复杂:

基础用户自定义加密(对称加密)

<?php
class UserEncryption {
    private string $method;
    private string $key;
    private string $iv;
    public function __construct(string $method = 'aes-256-cbc') {
        $this->method = $method;
        // 从配置或数据库获取用户的自定义密钥
    }
    // 用户自定义加密密钥
    public function setUserKey(string $userKey): void {
        // 使用用户密码派生密钥
        $this->key = hash('sha256', $userKey, true);
    }
    // 加密数据
    public function encrypt(string $data): string {
        $ivLength = openssl_cipher_iv_length($this->method);
        $iv = openssl_random_pseudo_bytes($ivLength);
        $encrypted = openssl_encrypt(
            $data, 
            $this->method, 
            $this->key, 
            OPENSSL_RAW_DATA, 
            $iv
        );
        // 将IV和加密数据组合
        return base64_encode($iv . $encrypted);
    }
    // 解密数据
    public function decrypt(string $encryptedData): string|false {
        $data = base64_decode($encryptedData);
        $ivLength = openssl_cipher_iv_length($this->method);
        $iv = substr($data, 0, $ivLength);
        $encrypted = substr($data, $ivLength);
        return openssl_decrypt(
            $encrypted, 
            $this->method, 
            $this->key, 
            OPENSSL_RAW_DATA, 
            $iv
        );
    }
}
// 使用示例
$userEnc = new UserEncryption();
$userEnc->setUserKey('user_specific_password_123');
$encrypted = $userEnc->encrypt('敏感数据内容');
echo "加密后: " . $encrypted . PHP_EOL;
echo "解密后: " . $userEnc->decrypt($encrypted);
?>

多用户加密管理系统

<?php
class MultiUserEncryption {
    private PDO $db;
    public function __construct(PDO $db) {
        $this->db = $db;
    }
    // 创建用户加密密钥
    public function createUserKey(int $userId, string $userPassword): bool {
        // 生成32字节随机密钥
        $encryptionKey = random_bytes(32);
        // 使用用户密码加密存储密钥
        $protectedKey = $this->protectKeyWithPassword($encryptionKey, $userPassword);
        // 存储到数据库
        $stmt = $this->db->prepare(
            "INSERT INTO user_encryption_keys (user_id, protected_key, created_at) 
             VALUES (?, ?, NOW())"
        );
        return $stmt->execute([$userId, base64_encode($protectedKey)]);
    }
    // 使用密码保护密钥
    private function protectKeyWithPassword(string $key, string $password): string {
        $salt = random_bytes(16);
        $passwordKey = hash_pbkdf2('sha256', $password, $salt, 10000, 32, true);
        $iv = random_bytes(16);
        $encrypted = openssl_encrypt(
            $key, 
            'aes-256-cbc', 
            $passwordKey, 
            OPENSSL_RAW_DATA, 
            $iv
        );
        return $salt . $iv . $encrypted;
    }
    // 提取用户密钥
    private function extractUserKey(int $userId, string $password): ?string {
        $stmt = $this->db->prepare(
            "SELECT protected_key FROM user_encryption_keys WHERE user_id = ?"
        );
        $stmt->execute([$userId]);
        $row = $stmt->fetch();
        if (!$row) return null;
        $data = base64_decode($row['protected_key']);
        $salt = substr($data, 0, 16);
        $iv = substr($data, 16, 16);
        $encrypted = substr($data, 32);
        $passwordKey = hash_pbkdf2('sha256', $password, $salt, 10000, 32, true);
        return openssl_decrypt($encrypted, 'aes-256-cbc', $passwordKey, OPENSSL_RAW_DATA, $iv);
    }
    // 加密用户数据
    public function encryptUserData(int $userId, string $password, string $data): string {
        $key = $this->extractUserKey($userId, $password);
        if (!$key) throw new Exception("无法获取用户密钥");
        $iv = random_bytes(16);
        $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        return base64_encode($iv . $encrypted);
    }
    // 解密用户数据
    public function decryptUserData(int $userId, string $password, string $encryptedData): string {
        $key = $this->extractUserKey($userId, $password);
        if (!$key) throw new Exception("无法获取用户密钥");
        $data = base64_decode($encryptedData);
        $iv = substr($data, 0, 16);
        $encrypted = substr($data, 16);
        $decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        if ($decrypted === false) throw new Exception("解密失败");
        return $decrypted;
    }
}
// 数据库表结构
/*
CREATE TABLE user_encryption_keys (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT UNIQUE NOT NULL,
    protected_key TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
*/
?>

用户自定义加密算法选择器

<?php
class CustomEncryptionSelector {
    private array $availableMethods = [
        'aes-256-cbc' => 'AES-256-CBC (推荐)',
        'aes-128-cbc' => 'AES-128-CBC',
        'des-ede3-cbc' => '3DES',
        'chacha20' => 'ChaCha20',
    ];
    private array $userPreferences;
    public function __construct(array $userPreferences = []) {
        $this->userPreferences = $userPreferences;
    }
    // 获取可用加密方法
    public function getAvailableMethods(): array {
        return $this->availableMethods;
    }
    // 用户选择加密方法
    public function setUserMethod(string $method): bool {
        if (!isset($this->availableMethods[$method])) {
            return false;
        }
        $this->userPreferences['method'] = $method;
        return true;
    }
    // 带认证的加密(GCM模式)
    public function encryptWithAuth(string $data, string $userKey): string {
        $method = $this->userPreferences['method'] ?? 'aes-256-gcm';
        $key = hash('sha256', $userKey, true);
        $ivLength = openssl_cipher_iv_length($method);
        $iv = openssl_random_pseudo_bytes($ivLength);
        $tag = '';
        $encrypted = openssl_encrypt(
            $data, 
            $method, 
            $key, 
            OPENSSL_RAW_DATA, 
            $iv, 
            $tag, 
            '', 
            16
        );
        // 包含认证标签
        return base64_encode($iv . $tag . $encrypted);
    }
    // 解密带认证的数据
    public function decryptWithAuth(string $encryptedData, string $userKey): string|false {
        $method = $this->userPreferences['method'] ?? 'aes-256-gcm';
        $key = hash('sha256', $userKey, true);
        $data = base64_decode($encryptedData);
        $ivLength = openssl_cipher_iv_length($method);
        $iv = substr($data, 0, $ivLength);
        $tag = substr($data, $ivLength, 16);
        $encrypted = substr($data, $ivLength + 16);
        return openssl_decrypt(
            $encrypted, 
            $method, 
            $key, 
            OPENSSL_RAW_DATA, 
            $iv, 
            $tag
        );
    }
}
// 使用示例
$selector = new CustomEncryptionSelector();
$selector->setUserMethod('aes-256-gcm'); // 用户选择的加密方法
$userKey = 'user_specific_encryption_password';
$encrypted = $selector->encryptWithAuth('需要加密的敏感数据', $userKey);
echo "加密结果: " . $encrypted . PHP_EOL;
echo "解密结果: " . $selector->decryptWithAuth($encrypted, $userKey);
?>

数据库配置存储方案

<?php
// 数据库配置表结构
/*
CREATE TABLE user_encryption_config (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL UNIQUE,
    encryption_method VARCHAR(50) DEFAULT 'aes-256-cbc',
    key_derivation_iterations INT DEFAULT 100000,
    salt VARCHAR(64) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
*/
class EncryptionConfigManager {
    private PDO $db;
    public function __construct(PDO $db) {
        $this->db = $db;
    }
    // 保存用户加密配置
    public function saveEncryptionConfig(int $userId, array $config): bool {
        $stmt = $this->db->prepare(
            "INSERT INTO user_encryption_config 
             (user_id, encryption_method, key_derivation_iterations, salt)
             VALUES (?, ?, ?, ?)
             ON DUPLICATE KEY UPDATE
             encryption_method = VALUES(encryption_method),
             key_derivation_iterations = VALUES(key_derivation_iterations),
             salt = VALUES(salt)"
        );
        return $stmt->execute([
            $userId,
            $config['method'] ?? 'aes-256-cbc',
            $config['iterations'] ?? 100000,
            $config['salt'] ?? bin2hex(random_bytes(32))
        ]);
    }
    // 获取用户加密配置
    public function getEncryptionConfig(int $userId): ?array {
        $stmt = $this->db->prepare(
            "SELECT * FROM user_encryption_config WHERE user_id = ?"
        );
        $stmt->execute([$userId]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
}
?>

完整示例:完整的用户加密系统

<?php
// index.php - 使用示例
require_once 'user_encryption.php';
require_once 'encryption_config.php';
// 初始化数据库连接
$db = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
$userEnc = new MultiUserEncryption($db);
$configManager = new EncryptionConfigManager($db);
// 用户注册时创建加密配置
$userId = 123;
$userPassword = 'user_secure_password_2024';
try {
    // 创建用户加密密钥
    $userEnc->createUserKey($userId, $userPassword);
    // 保存用户加密偏好
    $configManager->saveEncryptionConfig($userId, [
        'method' => 'aes-256-gcm',
        'iterations' => 120000,
        'salt' => bin2hex(random_bytes(32))
    ]);
    // 加密用户数据
    $sensitiveData = "用户信用卡号: 4111-1111-1111-1111";
    $encrypted = $userEnc->encryptUserData(
        $userId, 
        $userPassword, 
        $sensitiveData
    );
    echo "加密成功!" . PHP_EOL;
    echo "加密数据: " . $encrypted . PHP_EOL;
    // 解密数据
    $decrypted = $userEnc->decryptUserData(
        $userId, 
        $userPassword, 
        $encrypted
    );
    echo "解密数据: " . $decrypted . PHP_EOL;
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}
?>

安全建议

  1. 密钥管理

    • 使用PBKDF2或bcrypt进行密钥派生
    • 不要在代码中硬编码密钥
    • 定期轮换加密密钥
  2. 加密算法选择

    • 推荐使用AES-256-GCM(带认证)
    • 避免使用DES或RC4等弱算法
    • 使用经过验证的加密库
  3. 数据完整性

    • 使用HMAC或GCM模式进行认证
    • 验证解密后的数据完整性
    • 防止篡改攻击
  4. 性能优化

    • 缓存常用加密密钥
    • 使用适当的迭代次数(100000-200000)
    • 考虑使用硬件加速(如AES-NI)
  5. 错误处理

    • 不要泄露详细的错误信息
    • 实现优雅的降级策略
    • 记录安全相关事件

这个实现提供了灵活的用户自定义加密功能,可以根据具体需求进行扩展和优化。

抱歉,评论功能暂时关闭!