PHP 加密安全常见漏洞与防护

```html PHP 加密安全常见漏洞与防护

PHP 加密安全常见漏洞与防护

加密不是“加了就安全”,错误的实现反而会引入严重风险。以下是 PHP 开发中高频出现的加密安全陷阱及正确实践。

❌ 漏洞一:使用过时/不安全的哈希算法

md5()sha1() 已被证实易受碰撞攻击,且无盐值(salt)导致彩虹表可批量破解。

危险示例:
$password_hash = md5($_POST['password']); // ❌ 绝对禁止
✅ 正确做法:使用 password_hash()(PHP 5.5+)
// 自动加盐 + 使用 bcrypt(推荐)或 argon2id
$hash = password_hash($_POST['password'], PASSWORD_ARGON2ID);
// 验证时无需关心盐值和算法细节
if (password_verify($_POST['password'], $hash)) {
    echo "登录成功";
}

❌ 漏洞二:手动实现加密/解密逻辑

自行拼接 IV、硬编码密钥、忽略认证加密(AEAD),极易导致 CBC 填充攻击或密文篡改。

危险示例(AES-CBC 无认证):
$key = 'hardcoded_key_16'; // ❌ 密钥硬编码 + 无认证
$iv = openssl_random_pseudo_bytes(16);
$cipher = openssl_encrypt($data, 'AES-128-CBC', $key, 0, $iv); // ❌ 易受 Padding Oracle 攻击
✅ 推荐:使用 sodium_crypto_secretbox()(PHP 7.2+)
$key = sodium_crypto_secretbox_keygen(); // 安全生成密钥
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted = sodium_crypto_secretbox($data, $nonce, $key);
// 验证+解密一步完成,失败直接返回 false
$decrypted = sodium_crypto_secretbox_open($encrypted, $nonce, $key);

❌ 漏洞三:混淆 ≠ 加密

base64_encode()str_rot13() 等仅是编码/变换,无密钥、无熵,完全不具备保密性。

典型误用:
$token = base64_encode("user_id=123&role=admin"); // ❌ 可瞬间解码

✅ 正确方案:敏感数据应存储于服务端 Session;若需客户端传递,使用 带签名的 JWT(如 firebase/php-jwt)或短期有效、服务端校验的一次性 Token。

📌 关键原则总结

  • 哈希密码 → 用 password_hash() / password_verify()
  • 加密敏感数据 → 优先选 libsodiumsodium_crypto_secretboxsodium_crypto_aead
  • 绝不硬编码密钥 → 使用环境变量或密钥管理服务(如 HashiCorp Vault)
  • 避免自研密码学逻辑 —— 即使是“简单替换”也违背 Kerckhoffs 原则

安全不是功能开关,而是贯穿设计、开发与运维的持续实践。从今天起,让每一行加密代码都经得起专业审视。

```