如何用PHP项目实现加密解密?

wen java案例 2

本文目录导读:

如何用PHP项目实现加密解密?

  1. 使用 OpenSSL 扩展(推荐用于通用加密)
  2. 使用 Sodium 扩展(现代安全方案,PHP 7.2+)
  3. 可逆哈希(不适合加密,仅用于密码存储)
  4. 数据库字段级加密(MySQL AES)
  5. 配置文件加密
  6. 最佳实践建议

在PHP项目中实现加密解密,有多种方法,具体选择取决于你的需求(如加密强度、性能、是否可逆等),以下是几种常见且安全的实现方式:

使用 OpenSSL 扩展(推荐用于通用加密)

对称加密(AES-256-GCM)

<?php
/**
 * AES-256-GCM 加密解密示例
 * 适用于:数据传输加密、敏感信息存储
 * 特点:带认证标签,防篡改
 */
class AesGcmEncryption {
    private string $key;
    private int $tagLength = 16; // 128位认证标签
    public function __construct(string $key) {
        // 确保密钥长度为32字节(256位)
        $this->key = hash('sha256', $key, true);
    }
    /**
     * 加密
     * @param string $plaintext 明文
     * @return string Base64编码的加密字符串(包含IV和认证标签)
     */
    public function encrypt(string $plaintext): string {
        $iv = openssl_random_pseudo_bytes(12); // 96位IV
        $tag = '';
        $ciphertext = openssl_encrypt(
            $plaintext,
            'aes-256-gcm',
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            '',
            $this->tagLength
        );
        // 组合IV + 密文 + 认证标签
        $encoded = base64_encode($iv . $ciphertext . $tag);
        return $encoded;
    }
    /**
     * 解密
     * @param string $ciphertext Base64编码的加密字符串
     * @return string|false 解密成功返回明文,失败返回false
     */
    public function decrypt(string $ciphertext): string|false {
        $decoded = base64_decode($ciphertext);
        // 提取IV、密文和认证标签
        $iv = substr($decoded, 0, 12);
        $tag = substr($decoded, -$this->tagLength);
        $encryptedData = substr($decoded, 12, -$this->tagLength);
        $plaintext = openssl_decrypt(
            $encryptedData,
            'aes-256-gcm',
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag
        );
        return $plaintext;
    }
}
// 使用示例
$encryption = new AesGcmEncryption('my-secret-key-12345');
$encrypted = $encryption->encrypt('Hello, World!');
echo "加密后: " . $encrypted . "\n";
$decrypted = $encryption->decrypt($encrypted);
echo "解密后: " . $decrypted . "\n";

使用 Sodium 扩展(现代安全方案,PHP 7.2+)

<?php
/**
 * Sodium 加密解密(现代且安全的加密库)
 * 适用于:需要最高安全标准的应用
 * 特点:简单易用,内置防篡改
 */
class SodiumEncryption {
    /**
     * 加密
     * @param string $plaintext 明文
     * @param string $key 密钥(必须32字节)
     * @return string Base64编码的加密结果
     */
    public static function encrypt(string $plaintext, string $key): string {
        // 生成随机nonce
        $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
        // 加密
        $ciphertext = sodium_crypto_secretbox($plaintext, $nonce, $key);
        // 组合nonce + 密文
        return base64_encode($nonce . $ciphertext);
    }
    /**
     * 解密
     * @param string $ciphertext Base64编码的加密字符串
     * @param string $key 密钥(必须32字节)
     * @return string|false 解密成功返回明文,失败返回false
     */
    public static function decrypt(string $ciphertext, string $key): string|false {
        $decoded = base64_decode($ciphertext);
        if (mb_strlen($decoded, '8bit') < SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES) {
            return false;
        }
        $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
        $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
        $plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
        // 清除敏感数据
        sodium_memzero($nonce);
        return $plaintext;
    }
    /**
     * 生成安全随机密钥
     * @return string 32字节的密钥
     */
    public static function generateKey(): string {
        return random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
    }
}
// 使用示例
$key = SodiumEncryption::generateKey();
echo "密钥 (Base64): " . base64_encode($key) . "\n";
$encrypted = SodiumEncryption::encrypt('Hello, World!', $key);
echo "加密后: " . $encrypted . "\n";
$decrypted = SodiumEncryption::decrypt($encrypted, $key);
echo "解密后: " . $decrypted . "\n";

可逆哈希(不适合加密,仅用于密码存储)

<?php
/**
 * 密码哈希(不可逆,用于存储密码)
 * 注意:这不是加密,是单向哈希
 */
class PasswordHasher {
    /**
     * 创建密码哈希
     */
    public static function hash(string $password): string {
        return password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
    }
    /**
     * 验证密码
     */
    public static function verify(string $password, string $hash): bool {
        return password_verify($password, $hash);
    }
}
// 使用示例
$hash = PasswordHasher::hash('my-secret-password');
echo "密码哈希: " . $hash . "\n";
$isValid = PasswordHasher::verify('my-secret-password', $hash);
echo "密码验证: " . ($isValid ? '有效' : '无效') . "\n";

数据库字段级加密(MySQL AES)

<?php
/**
 * 数据库字段加密(使用MySQL内置函数)
 * 适用于:需要在数据库层面进行加密的场景
 */
class DatabaseEncryption {
    private PDO $pdo;
    private string $encryptionKey;
    public function __construct(PDO $pdo, string $key) {
        $this->pdo = $pdo;
        $this->encryptionKey = $key;
    }
    /**
     * 插入加密数据
     */
    public function insertEncryptedData(string $table, string $column, string $plaintext): bool {
        $sql = "INSERT INTO $table ($column) VALUES (AES_ENCRYPT(:plaintext, :key))";
        $stmt = $this->pdo->prepare($sql);
        return $stmt->execute([
            ':plaintext' => $plaintext,
            ':key' => $this->encryptionKey
        ]);
    }
    /**
     * 查询解密数据
     */
    public function getDecryptedData(string $table, string $column, int $id): ?string {
        $sql = "SELECT AES_DECRYPT($column, :key) FROM $table WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':key' => $this->encryptionKey,
            ':id' => $id
        ]);
        $result = $stmt->fetchColumn();
        return $result ?: null;
    }
}

配置文件加密

<?php
/**
 * 配置文件加密(适用于.env文件等)
 * 特点:简单,适合存储API密钥等敏感配置
 */
class ConfigEncryption {
    private string $key;
    private string $method = 'aes-256-cbc';
    public function __construct(string $key) {
        $this->key = hash('sha256', $key, true);
    }
    /**
     * 加密配置文件值
     */
    public function encryptConfigValue(string $value): string {
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->method));
        $encrypted = openssl_encrypt($value, $this->method, $this->key, 0, $iv);
        return base64_encode($iv . '::' . $encrypted);
    }
    /**
     * 解密配置文件值
     */
    public function decryptConfigValue(string $encryptedValue): string|false {
        $data = base64_decode($encryptedValue);
        $parts = explode('::', $data, 2);
        if (count($parts) !== 2) {
            return false;
        }
        [$iv, $encrypted] = $parts;
        return openssl_decrypt($encrypted, $this->method, $this->key, 0, $iv);
    }
}
// 使用示例
$configEnc = new ConfigEncryption('my-config-key');
$encryptedApiKey = $configEnc->encryptConfigValue('sk-xxxxx');
echo "加密的API密钥: " . $encryptedApiKey . "\n";
$decryptedApiKey = $configEnc->decryptConfigValue($encryptedApiKey);
echo "解密的API密钥: " . $decryptedApiKey . "\n";

最佳实践建议

  1. 选择合适的加密方法

    • 数据加密:使用 AES-256-GCMSodium
    • 密码存储:使用 password_hash()(不可逆)
    • 临时令牌:使用 openssl_random_pseudo_bytes()
  2. 密钥管理

    • 将密钥存储在环境变量或密钥管理服务中
    • 不要硬编码密钥到代码中
    • 定期轮换密钥
  3. 安全注意事项

    • 始终使用随机IV/nonce
    • 使用认证加密(如GCM模式)防止篡改
    • 不要使用过时的算法(如MD5、SHA1、DES)
    • 对于敏感数据,考虑在传输层使用HTTPS
  4. 性能考虑

    • 对称加密比非对称加密快得多
    • Sodium比OpenSSL在某些操作上更快
    • 对于批量加密,考虑使用流式加密

选择哪种方法取决于你的具体需求:如果需要跨平台兼容,选OpenSSL;如果追求最高安全性且PHP 7.2+,选Sodium;如果只是密码存储,用password_hash()。

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