PHP 加密安全常见漏洞与防护
在 Web 开发中,错误的加密实践比不加密更危险——它会给人以“安全”的错觉。以下是 PHP 中最典型的加密安全陷阱及正确应对方案。
❌ 漏洞一:使用过时的 hash 函数(md5/sha1)
md5() 和 sha1() 已被证明易受碰撞攻击,且无盐值、无迭代,无法抵御彩虹表或暴力破解。
// ❌ 危险示例:明文密码直接哈希
$password = $_POST['password'];
$hash = md5($password); // 绝对禁止!
✅ 防护:使用 password_hash() + password_verify()
PHP 内置函数自动加盐、使用 bcrypt(推荐)或 Argon2i 算法,支持自适应迭代强度:
// ✅ 安全示例:注册时哈希密码
$hash = password_hash($_POST['password'], PASSWORD_ARGON2ID, [
'memory_cost' => 65536, // 64MB 内存
'time_cost' => 4,
'threads' => 3
]);
// 登录验证
if (password_verify($_POST['password'], $stored_hash)) {
// 验证成功
}
❌ 漏洞二:手动实现加密/解密逻辑
自行拼接 IV、选择弱算法(如 ECB 模式)、硬编码密钥等,极易引入侧信道或填充预言攻击。
✅ 防护:使用 OpenSSL 标准封装
务必使用 openssl_encrypt() / openssl_decrypt(),并严格管理密钥与 IV:
// ✅ 安全示例:AES-256-GCM 加密(带认证)
$key = sodium_crypto_secretbox_keygen(); // 或从安全密钥管理服务获取
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES);
$ciphertext = sodium_crypto_aead_aes256gcm_encrypt(
$data, $associated_data, $nonce, $key
);
// 解密(自动验证完整性)
$plaintext = sodium_crypto_aead_aes256gcm_decrypt(
$ciphertext, $associated_data, $nonce, $key
);
⚠️ 关键原则提醒
• 密钥永不硬编码:使用环境变量或密钥管理系统(如 HashiCorp Vault)。
• 敏感数据绝不明文存储:数据库字段如 token、API key 必须加密。
• 定期轮换密钥与哈希算法:利用
• 敏感数据绝不明文存储:数据库字段如 token、API key 必须加密。
• 定期轮换密钥与哈希算法:利用
password_needs_rehash() 平滑升级旧哈希。
安全不是功能,而是贯穿开发全生命周期的习惯。从今天起,用 password_hash() 替代 md5(),用 sodium_crypto_* 替代自写加密——让安全成为默认,而非补丁。