PHP 加密密钥管理与安全存储

```html PHP 加密密钥管理与安全存储

PHP 加密密钥管理与安全存储

在 PHP 应用中,正确管理加密密钥是保障数据安全的核心环节。密钥一旦泄露或硬编码,再强的加密算法也形同虚设。

❌ 常见错误实践

以下方式极不安全,应绝对避免:

  • define('ENCRYPTION_KEY', 'my-secret-123!');(硬编码在代码中)
  • 将密钥写入 Git 仓库或 Web 可访问目录
  • 使用弱熵源生成密钥(如 md5(time().rand())

✅ 推荐安全实践

1. 使用环境变量隔离密钥

通过 .env 文件 + vlucas/phpdotenv 加载,确保密钥不随代码发布:

# .env(禁止提交至 Git!)
APP_ENCRYPTION_KEY=base64:Kv9XzF7YqR2tBnLpWmJvDcSgHkN5aQrEiUoTjVwXyZ1=

2. 安全密钥生成与验证

使用 random_bytes() 生成高强度密钥,并严格校验格式:

<?php
// 生成 32 字节 AES-256 密钥(推荐)
$key = random_bytes(32);
echo 'Base64 编码密钥: ' . base64_encode($key) . "\n";

// 验证密钥长度(AES-256 必须为 32 字节)
if (strlen($key) !== 32) {
    throw new InvalidArgumentException('密钥长度必须为 32 字节');
}
?>

3. 安全加密示例(AES-256-GCM)

GCM 模式提供加密+认证,防止篡改:

<?php
function encrypt(string $plaintext, string $key): string
{
    $iv = random_bytes(12); // GCM 标准 IV 长度:12 字节
    $tag = '';
    
    $ciphertext = openssl_encrypt(
        $plaintext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag,
        '', // aad(可选)
        16 // tag 长度
    );
    
    if ($ciphertext === false) {
        throw new RuntimeException('加密失败: ' . openssl_error_string());
    }
    
    return base64_encode($iv . $tag . $ciphertext);
}

function decrypt(string $encrypted, string $key): string
{
    $data = base64_decode($encrypted);
    $iv = substr($data, 0, 12);
    $tag = substr($data, 12, 16);
    $ciphertext = substr($data, 28);
    
    $plaintext = openssl_decrypt(
        $ciphertext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );
    
    if ($plaintext === false) {
        throw new RuntimeException('解密失败或密钥错误');
    }
    
    return $plaintext;
}
?>
⚠️ 重要提醒:密钥必须保密、不可预测、长度合规;IV/Tag 每次加密均需随机生成且可公开传输;永远不要重用 IV + 密钥组合。

进阶建议

  • 密钥轮换:定期更新密钥并迁移旧数据(配合版本号标识)
  • 密钥分层:用主密钥(KEK)加密数据密钥(DEK),主密钥交由 KMS(如 AWS KMS、HashiCorp Vault)托管
  • 权限最小化:Web 服务器进程仅对密钥文件拥有读取权限(chmod 600

安全不是功能,而是持续实践。从今天起,让每一把密钥都住在它该住的地方——而不是代码里。

```