结合base64_encode与HMAC SHA512及password_hash存密码是否安全?
你的密码哈希方案分析与优化建议
嘿,先给你指出来代码里一个容易忽略的关键错误:PHP的hash_hmac()函数签名是hash_hmac($algo, $data, $key, $raw_output = false)——你现在把第三个参数传成了true,这会让PHP把布尔值true转换成字符串"1"当作HMAC的密钥。用固定的、公开的"1"当密钥,这步HMAC操作完全起不到任何额外的安全作用,反而平白增加了复杂度。
接下来回到你最关心的问题:这个方案到底安全吗?
为什么你的预处理步骤是多余甚至有风险的
password_hash()是PHP官方力推的密码存储方案,它本身已经把安全密码哈希需要的所有细节都处理好了:
- 自动生成随机盐值,彻底杜绝彩虹表攻击
- 默认使用当前最安全的算法(PHP 5.5+默认是bcrypt,PHP 7.4+开始支持更安全的Argon2,而且会自动跟着PHP的升级更新算法)
- 自动配置合适的迭代次数、内存消耗等参数,平衡安全性和服务器性能
你额外加的hash_hmac+base64_encode步骤,不仅没提升安全性,反而可能带来问题:
- 纯纯浪费服务器计算资源,没有任何安全增益
- 要是密钥处理不当(比如你现在这种固定密钥的情况),反而可能降低安全性——HMAC的核心是用唯一且保密的密钥,密钥泄露或固定的话,HMAC就失去意义了
- 增加代码复杂度,更容易像这次一样出现参数传错的低级错误
更安全、更省心的极简方案
直接用password_hash()处理原始密码就行,完全不需要任何额外预处理:
存储密码到数据库
$userPassword = "用户输入的密码"; // 直接用PASSWORD_DEFAULT,PHP会自动选当前最安全的算法 $storedHash = password_hash($userPassword, PASSWORD_DEFAULT); // 把$storedHash存进数据库就行
验证登录密码
$userInputPassword = "用户登录时输的密码"; $storedHash = $rowsSesion['pass']; // 从数据库取出来的哈希值 if (password_verify($userInputPassword, $storedHash)) { // 验证通过,允许登录 } else { // 密码不对,拒绝登录 }
这个方案的好处不用多说:
- 完全符合业界安全标准,PHP官方持续维护,跟着安全趋势自动升级
- 代码简洁到离谱,几乎不可能出错
- 后续PHP更新更安全的算法时,你完全不用改代码,
password_hash()会自动适配
额外的安全小 tips
- 别限制用户密码的长度(只要不是离谱的长就行),
password_hash()能处理任意长度的密码 - 永远别自己瞎写加盐、哈希逻辑,官方的实现比你自己写的靠谱一万倍
- 可以用
password_needs_rehash()在用户登录时自动更新旧哈希值到新算法(比如从bcrypt升级到Argon2):
if (password_verify($userInputPassword, $storedHash)) { // 检查当前哈希是否需要升级到新算法 if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) { $newHash = password_hash($userInputPassword, PASSWORD_DEFAULT); // 更新数据库里的哈希值为$newHash } // 登录成功 }
总结一下:你现在的方案不仅多余,还存在密钥错误的问题,赶紧换成原生的password_hash()+password_verify()组合,这是PHP场景下最安全、最省心的密码存储方式。
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

