PHP 密码加密方案对比:MD5、SHA、bcrypt
密码存储是Web安全的核心环节,明文存储密码一旦发生数据泄露将造成不可估量的损失。PHP生态中常见的密码加密方案有MD5、SHA系列和bcrypt,三者的安全性和适用场景差异极大,本文将对它们进行对比并给出最佳实践。
1. MD5 加密方案
MD5是最早被广泛使用的哈希算法,输出32位十六进制字符串,计算速度极快。早期很多PHP项目会用MD5存储密码,甚至自行加盐处理,但现在已完全不推荐用于密码存储。
// MD5 加密示例(仅作演示,禁止用于生产环境)
$password = 'user_password';
$hash = md5($password);
// 验证逻辑
$inputPassword = $_POST['password'];
if (md5($inputPassword) === $hash) {
echo '验证通过';
}
MD5的致命缺陷是:计算速度极快,普通GPU每秒可计算上百亿次MD5哈希,且存在大量公开的彩虹表,即使自行加盐,一旦数据库泄露、盐值同时暴露,弱密码仍可被瞬间破解。
2. SHA 系列加密方案
SHA系列包含SHA-1、SHA-256、SHA-512等变种,输出长度更长,碰撞概率比MD5低,常被误认为比MD5更安全。但SHA系列仍属于快哈希算法,同样不推荐用于密码存储。
// SHA-256 加密示例(仅作演示,禁止用于生产环境)
$salt = '自定义盐值'; // 自行加盐无法解决快哈希的本质问题
$hash = hash('sha256', $salt . $password);
// 验证逻辑
if (hash('sha256', $salt . $inputPassword) === $hash) {
echo '验证通过';
}
SHA系列的设计初衷是数据完整性校验、数字签名等场景,而非密码存储。其计算速度仅略低于MD5,普通GPU每秒可计算数十亿次SHA-256哈希,弱密码依然极易被暴力破解。
3. bcrypt 加密方案
bcrypt是专为密码存储设计的慢哈希算法,是PHP官方推荐的密码加密方案,自PHP 5.5起提供了内置的`password_hash`和`password_verify`函数,无需自行处理加盐、哈希逻辑。
// bcrypt 加密示例(生产环境推荐)
$password = 'user_password';
// 生成密码哈希,自动添加随机盐,PASSWORD_DEFAULT 会随PHP版本升级为更安全的算法
$hash = password_hash($password, PASSWORD_DEFAULT);
// 验证逻辑,内置函数自动处理盐值比对,规避时序攻击
$inputPassword = $_POST['password'];
if (password_verify($inputPassword, $hash)) {
echo '验证通过';
// 若成本因子更新,可重新生成哈希并更新数据库
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
$newHash = password_hash($inputPassword, PASSWORD_DEFAULT);
// 更新数据库中的哈希值
}
}
bcrypt的核心优势是:慢哈希特性,可通过成本因子调整计算耗时,默认成本因子下每次哈希需几十毫秒,暴力破解成本是快哈希的百万倍以上;自动生成随机盐,避免彩虹表攻击;哈希值自包含盐和算法信息,无需单独存储盐值。PHP 7.2+还可选择更安全的Argon2算法,安全性优于bcrypt。
方案对比总览
| 加密方案 | 安全性 | 计算速度 | 是否推荐用于密码存储 | 适用场景 |
|---|---|---|---|---|
| MD5 | 极低,易被彩虹表、暴力破解 | 极快 | 否 | 仅用于文件完整性校验等非安全场景 |
| SHA系列(SHA-1/256/512) | 低,快哈希易被暴力破解 | 快 | 否 | 数据签名、完整性校验,不推荐存密码 |
| bcrypt/Argon2 | 高,慢哈希+自动加盐 | 慢(可调成本因子) | 是 | 密码存储、敏感信息加密 |
最佳实践
1. 禁止使用MD5、SHA系列快哈希算法存储密码;
2. 优先使用PHP内置的`password_hash`/`password_verify`,PHP 7.2+可使用更安全的Argon2算法;
3. 不要自行实现加密、加盐逻辑,避免引入安全漏洞;
4. 定期根据硬件算力提升调整哈希成本因子,平衡安全性和接口性能。