PHP 数据加密最佳实践

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

PHP 数据加密最佳实践

在 Web 应用中,安全地处理敏感数据(如密码、API 密钥、用户身份信息)是开发者的核心责任。PHP 提供了成熟、可靠的加密工具,但错误使用仍可能导致严重风险。以下是经过验证的加密实践指南。

✅ 1. 密码哈希:永远使用 password_hash()

切勿手动实现 MD5、SHA1 或自行加盐——它们已被证明不安全。

// ✅ 正确:使用 bcrypt(PHP 5.5+ 默认算法)
$hash = password_hash('user_password_123', PASSWORD_ARGON2ID, [
    'memory_cost' => 65536, // 64MB
    'time_cost'   => 4,
    'threads'     => 3
]);

// 验证时使用 password_verify()
if (password_verify($input, $hash)) {
    echo "登录成功";
}

提示:优先选择 PASSWORD_ARGON2ID(需 PHP 7.2+ 及 libsodium),它抗 GPU/ASIC 暴力破解;若不可用,PASSWORD_DEFAULT 亦可(当前为 bcrypt)。

✅ 2. 敏感数据加密:使用 sodium_crypto_secretbox()

对需要「可逆加密」的字段(如数据库中的邮箱、手机号),应使用现代对称加密,而非过时的 mcrypt 或 OpenSSL 的弱模式。

// ✅ 安全的 AEAD 加密(认证加密)
$key = sodium_crypto_secretbox_keygen();
$nonce = sodium_crypto_secretbox_noncegen();
$message = 'user@example.com';

$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);
$decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);

// 存储时:base64_encode($nonce . $ciphertext) + 安全保管 $key(如环境变量)
echo base64_encode($nonce . $ciphertext);

关键原则:密钥绝不硬编码;使用 libsodium(PHP 7.2+ 内置),它自动处理填充、认证与随机数生成。

⚠️ 需避免的陷阱

❌ 错误示例:
md5($pass . $salt) —— 易受彩虹表和暴力攻击
openssl_encrypt(..., 'AES-128-CBC') —— 若未手动实现 HMAC 认证,存在填充预言攻击风险
• 将密钥写入代码或配置文件 —— 应通过 $_ENV['ENCRYPTION_KEY'] 或密钥管理服务(如 AWS KMS)注入

🔐 补充建议

  • 密钥轮换:定期更新加密密钥,并支持双密钥解密过渡期;
  • 最小权限:加密密钥仅授予必要服务,数据库用户禁用 FILE 权限;
  • 日志脱敏:确保错误日志不记录明文密码或密文(error_log() 前过滤敏感字段)。

安全不是功能,而是持续实践。从今天起,用 password_hash() 替代所有自定义密码哈希,用 sodium_crypto_secretbox() 替代所有手写 AES 实现——这是 PHP 开发者最务实的安全升级。

```