PHP 数据库敏感数据加密存储方案

```html PHP 数据库敏感数据加密存储方案

PHP 数据库敏感数据加密存储方案

在用户注册、支付、身份认证等场景中,密码、手机号、身份证号、银行卡号等属于敏感数据,绝不可明文存储于数据库。PHP 提供了成熟的安全工具链,本文介绍一种符合 OWASP 和 GDPR 原则的端到端加密实践方案。

✅ 核心原则

  • 加密而非哈希:对需可逆读取的字段(如手机号、邮箱)使用对称加密;密码等仅需验证的字段仍用 password_hash() 哈希。
  • 密钥分离:主密钥(Master Key)不硬编码,建议通过环境变量或密钥管理服务(KMS)注入。
  • AES-256-GCM:采用带认证的加密模式,防篡改、防重放,且 PHP 7.1+ 原生支持。

🔐 示例:加密存储用户手机号

<?php
// config.php —— 从环境变量安全加载密钥
$encryptionKey = $_ENV['APP_ENCRYPTION_KEY'] ?? '32-byte-secret-key-for-aes-256-gcm';
if (mb_strlen($encryptionKey, '8bit') !== 32) {
    throw new RuntimeException('Encryption key must be exactly 32 bytes.');
}

function encryptField(string $plaintext, string $key): string
{
    $iv = random_bytes(12); // GCM recommended IV length: 12 bytes
    $tag = '';
    $ciphertext = openssl_encrypt(
        $plaintext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag,
        '', // aad (optional)
        16 // tag length
    );
    if ($ciphertext === false) {
        throw new RuntimeException('Encryption failed: ' . openssl_error_string());
    }
    return base64_encode($iv . $tag . $ciphertext);
}

function decryptField(string $encrypted, string $key): string
{
    $data = base64_decode($encrypted);
    $iv = mb_substr($data, 0, 12, '8bit');
    $tag = mb_substr($data, 12, 16, '8bit');
    $ciphertext = mb_substr($data, 28, null, '8bit');

    $plaintext = openssl_decrypt(
        $ciphertext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );
    if ($plaintext === false) {
        throw new RuntimeException('Decryption failed: ' . openssl_error_string());
    }
    return $plaintext;
}

// 使用示例
$phone = '+8613800138000';
$encryptedPhone = encryptField($phone, $encryptionKey);
echo "加密后: {$encryptedPhone}\n"; // 存入数据库 users.phone_encrypted 字段

$decryptedPhone = decryptField($encryptedPhone, $encryptionKey);
echo "解密后: {$decryptedPhone}\n"; // 显示或校验时调用
?>

💡 最佳实践提醒

⚠️ 切勿:将密钥写死在代码中;使用 ECB 模式;忽略 IV/Tag 安全存储;在日志中打印加密前数据。

此外,建议结合 Laravel 的 encrypt()/decrypt() 或 Symfony 的 Symfony\Component\Security\Crypto\Encryptor(已弃用,推荐使用 defuse/php-encryption 库)进一步提升可靠性。生产环境务必启用 PHP 的 OpenSSL 扩展,并定期轮换密钥。

安全不是功能,而是贯穿生命周期的设计习惯。从今天起,让每一行敏感数据,都拥有自己的数字盾牌。

```