PHP密码哈希与加盐:2025年安全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

密码成为目标:为什么旧方法不再有效

\n

想象一下:你是一名开发人员,正在编写一个注册系统。看起来能有多简单?获取密码,通过md5处理,保存到数据库。但在2025年,这种方法——直接通向漏洞之路。现代攻击、GPU暴力破解和彩虹表会在几秒钟内将弱哈希化为乌有。Stack Overflow上一个有数千次浏览的问题——「Secure hash and salt for PHP passwords」——仍然具有现实意义,我们将一劳永逸地解决它。

\n

在本文中,您将学习如何使用现代算法、内置函数和盐(salt)在PHP中正确地对密码进行哈希处理。我们将社区的最佳答案改编为教育内容,并向您展示即使在2025年也能如何保护用户。

\n\n

为什么md5和sha1是邪恶的

\n

如果您仍然使用md5或sha1来存储密码——请停下来。这些算法是为速度而设计的,而不是为安全。在2025年,GPU每秒可以破解数十亿个md5哈希。添加盐(随机字符串)也无济于事:彩虹表可以被绕过,但速度仍然是致命的。

\n
    \n
  • Md5: 2^128种可能性——几分钟内即可破解。
  • \n
  • Sha1: 稍好一些,但同样过时了。
  • \n
  • 不加慢化的盐: 如果哈希很快,盐只能延迟攻击。
  • \n
\n

相反,我们需要「慢化」算法——那些需要时间和内存的算法。这正是password_hash所使用的。

\n\n

password_hash 和 password_verify:PHP内置的解决方案

\n

自PHP 5.5起,出现了两个函数,它们解决了90%的密码安全问题:password_hash和password_verify。它们会自动生成加密安全的盐,并使用能够抵抗暴力破解的算法。在2025年,这是标准做法,不要再自己造轮子了!

\n\n

它是如何工作的?

\n

password_hash函数接受一个密码和一个算法(默认是bcrypt,但也可以指定argon2)。它返回一个已经包含盐和参数的字符串。您不需要单独存储盐——它就在哈希内部。

\n
<?php\n// 哈希密码\n$password = "SuperSecret123!";\n$hash = password_hash($password, PASSWORD_DEFAULT);\n\necho $hash; // $2y$10$... (60个字符)\n?>\n
\n

现在在登录时验证密码:

\n
<?php\n$inputPassword = "SuperSecret123!";\n$storedHash = "$2y$10$..."; // 来自数据库\n\nif (password_verify($inputPassword, $storedHash)) {\n    echo "密码正确!";\n} else {\n    echo "密码错误。";\n}\n?>\n
\n

一切都非常简单。password_verify会自动从哈希中提取盐并验证密码。无需任何额外操作。

\n\n

算法选择:bcrypt vs argon2

\n

在2025年,您有两个主要选择:

\n
    \n
  • Bcrypt (PASSWORD_BCRYPT): 久经考验,默认使用。能抵抗攻击,但需要配置cost factor。
  • \n
  • Argon2 (PASSWORD_ARGON2I 或 PASSWORD_ARGON2ID): 密码哈希竞赛的获胜者。更现代,需要更多内存,这使得GPU攻击更加困难。推荐用于新项目。
  • \n
\n

使用argon2的示例:

\n
<?php\n$hash = password_hash($password, PASSWORD_ARGON2ID, [\n    'memory_cost' => 1 << 17, // 128 MB\n    'time_cost'   => 4,\n    'threads'     => 2\n]);\n?>\n
\n

memory_cost参数——内存大小,以千字节为单位。越高越安全,但也越慢。对于生产环境,请在您自己的服务器上进行测试。

\n\n

盐(salt):它是如何工作的以及为什么不需要单独处理

\n

许多新手会问:「如何手动添加盐?」答案是:不需要。password_hash会为bcr生成22个字符的随机盐

博客

书籍推荐