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

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

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

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

❌ 常见错误实践

以下方式绝对禁止:

  • define('ENCRYPTION_KEY', 'my-secret-123!');(硬编码于代码中)
  • 将密钥写入 config.php 并提交至 Git 仓库
  • 使用弱随机源(如 rand() 或时间戳)生成密钥

✅ 推荐安全实践

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

通过系统环境变量加载密钥,避免代码污染:

# Linux/macOS:启动前设置
export APP_ENCRYPTION_KEY="base64:qUJv...ZmYzI="

# PHP 中读取(推荐使用 vlucas/phpdotenv 处理 .env)
$key = $_ENV['APP_ENCRYPTION_KEY'] ?? null;
if (!$key || !str_starts_with($key, 'base64:')) {
    throw new RuntimeException('Invalid encryption key');
}
$rawKey = base64_decode(substr($key, 7));

2. 使用 Sodium 扩展(PHP 7.2+ 内置)

Sodium 是现代、安全、易用的加密库,无需第三方依赖:

<?php
// 生成并安全存储密钥(仅执行一次!)
$key = sodium_crypto_secretbox_keygen();
file_put_contents('/etc/app/secret.key', $key, LOCK_EX); // 权限:600
chmod('/etc/app/secret.key', 0600);

// 运行时加载(确保 Web 服务器有读权限)
$key = file_get_contents('/etc/app/secret.key');
if ($key === false) {
    throw new RuntimeException('Failed to load encryption key');
}

// 加密示例
$message = 'Sensitive user data';
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);

// 存储 nonce + ciphertext(nonce 可公开)
$storage = base64_encode($nonce . $ciphertext);
?>

3. 密钥轮换与版本控制

为支持密钥更新,建议添加版本标识:

$encrypted = [
    'v' => 2, // 密钥版本
    'n' => base64_encode($nonce),
    'c' => base64_encode($ciphertext)
];
// 解密时根据 'v' 选择对应密钥文件
⚠️ 重要提醒: • 永远不要将密钥存入数据库或 Web 可访问目录; • 生产环境禁用 display_errors,防止密钥意外输出; • 定期审计密钥权限:ls -l /etc/app/secret.key 应显示 -rw-------

安全不是功能,而是持续实践。从今天起,让每一把密钥都住在它该住的地方——受控、隔离、可审计。

```