当前位置: 首页> 最新文章列表> 用 md5 存密码安全吗?聊聊 PHP md5 函数在密码存储中的常见误区

用 md5 存密码安全吗?聊聊 PHP md5 函数在密码存储中的常见误区

gitbox 2025-06-18

在 Web 开发中,用户密码的安全存储是一项基础且至关重要的任务。然而,尽管安全知识不断普及,仍有许多开发者在初学 PHP 或构建简单系统时,习惯性地使用 md5() 函数对用户密码进行加密存储。今天我们就来聊聊,用 md5 存密码到底安不安全,以及这一做法背后存在哪些常见误区。

一、PHP 中的 md5 函数是什么?

md5() 是 PHP 内置的一个哈希函数,它可以将任意长度的字符串转换成一个 32 字符长度的十六进制字符串。例如:

<span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-title function_ invoke__">md5</span></span><span>(</span><span><span class="hljs-string">'password123'</span></span><span>); </span><span><span class="hljs-comment">// 输出:482c811da5d5b4bc6d497ffa98491e38</span></span><span>
</span></span>

这是一个不可逆的散列过程(理论上)。早期许多开发者将其用于对用户密码进行“加密”存储,认为这样可以保护用户的隐私。

二、md5 用来存密码安全吗?

答案是:不安全,早已被淘汰。

主要原因有以下几点:

1. 计算速度太快,易被暴力破解

md5() 本意是用于校验数据完整性的哈希函数,它的计算速度极快。然而,正因为速度快,使得它非常容易被用于暴力破解攻击(brute force attack)或彩虹表攻击(rainbow table attack)。

攻击者可以在极短的时间内尝试大量组合来猜测出原始密码,特别是对于常见或弱密码几乎毫无抵抗能力。

2. 无加盐(salt)

md5() 是确定性函数——相同输入永远产生相同输出。这就导致如果两个用户的密码相同,其生成的哈希值也相同,攻击者只需破解一次,即可适用于多个账户。

而没有加盐的哈希存储方式,是非常容易被彩虹表击穿的。

3. 已广泛被破解

互联网上存在大量 md5 哈希与明文密码的映射数据库,例如:你只需要将 md5('123456') 得到的哈希值粘贴进搜索引擎,往往立刻能查到原始密码。

三、那该怎么办?更安全的做法是什么?

使用 password_hash()password_verify()

PHP 从 5.5 版本起提供了 password_hash()password_verify() 这两个函数,是目前推荐用于密码加密和验证的方式。

示例代码如下:

<span><span><span class="hljs-comment">// 生成密码哈希</span></span><span>
</span><span><span class="hljs-variable">$hash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">password_hash</span></span><span>(</span><span><span class="hljs-string">'password123'</span></span><span>, PASSWORD_DEFAULT);

</span><span><span class="hljs-comment">// 验证密码</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">password_verify</span></span><span>(</span><span><span class="hljs-string">'password123'</span></span><span>, </span><span><span class="hljs-variable">$hash</span></span><span>)) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">'密码正确'</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">'密码错误'</span></span><span>;
}
</span></span>

password_hash() 默认使用 bcrypt 算法,并自动生成随机盐值,内置抗击暴力破解和彩虹表攻击的机制。

为什么推荐它?

  • 自动加盐

  • 可配置计算强度(成本因子)

  • 可扩展(支持不同的算法,如 Argon2)

  • 官方维护,符合现代密码存储标准

四、小结

使用 md5() 存储密码是过时且危险的做法,虽然在早期项目中较为常见,但在今天已经不再安全。随着网络攻击手段的不断升级,开发者应摒弃陈旧的安全观念,使用更现代、更安全的方式来处理用户密码。

记住:安全不是靠“加密”,而是靠设计。
拥抱 password_hash(),拒绝 md5(),是对用户安全最基本的尊重。