PHP 数据加密最佳实践

```html PHP 数据加密最佳实践

PHP 数据加密最佳实践

在 Web 应用中,敏感数据(如用户密码、API 密钥、个人身份信息)必须安全存储与传输。PHP 提供了成熟、可靠的加密工具,但错误使用仍可能导致严重安全隐患。

✅ 首选:使用 password_hash()password_verify()

密码绝不可使用 MD5、SHA1 或简单 base64 编码——它们不是加密,而是单向哈希且无盐,极易被彩虹表破解。

// ✅ 正确:使用 bcrypt(PHP 5.5+ 原生支持)
$password = "user_secret_123";
$hash = password_hash($password, PASSWORD_ARGON2ID); // 推荐 Argon2id(PHP 7.2+)
// 或兼容性更强的:PASSWORD_BCRYPT

// 验证时无需关心算法细节
if (password_verify($inputPassword, $storedHash)) {
    echo "登录成功";
}

优势:自动加盐、自适应计算强度、算法升级后仍可验证旧哈希。

🔐 敏感字段加密:使用 sodium_crypto_secretbox()

对数据库中需「可逆加密」的字段(如邮箱、身份证号),推荐 PHP 内置的 libsodium(PHP 7.2+ 默认启用):

// 生成密钥(一次生成,安全保存于环境变量中!)
$key = sodium_crypto_secretbox_keygen();

// 加密
$message = "zhangsan@example.com";
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);

// 解密
$decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
echo $decrypted; // → "zhangsan@example.com"

注意:密钥 绝不硬编码,应通过 $_ENV['ENCRYPTION_KEY'] 从环境变量加载,并确保密钥长度为 32 字节。

⚠️ 绝对避免的陷阱

× 错误示例:
md5($password)sha1($password . $salt)
• 自实现 AES-CBC 而未正确处理 IV/填充/认证
• 使用 mcrypt_*(已废弃且不安全)
• 将密钥写死在代码或 Git 仓库中

📌 最佳实践清单

  • 密码:始终用 password_hash() + password_verify()
  • 敏感字段加密:优先选用 sodium_crypto_secretbox(AEAD 认证加密)
  • 密钥管理:使用环境变量 + 严格文件权限(如 chmod 600 .env
  • 传输层:强制 HTTPS(TLS 1.2+),禁用明文 HTTP
  • 定期轮换:对长期有效的加密密钥制定轮换策略

安全不是功能,而是贯穿开发全周期的习惯。选择现代、经过审计的原生函数,比任何“自研加密”都更可靠。

```