password_verify返回true但哈希不匹配,疑与密码长度限制有关
为什么超长拼接密码能用password_verify验证通过?
你判断的完全正确——问题根源就是Blowfish算法(PHP中password_hash默认的$2y$类型)的72字符密码长度限制。
Blowfish在处理密码哈希时,会直接截断超过72字符的部分,只取前72位进行计算。你的拼接密码$pass长度远超72字符,而你用来验证的$hash,本质上就是该密码前72位对应的哈希值。所以调用password_verify时,它同样会截断输入密码到前72位再和哈希比对,自然会返回true。
这种直接拼接密钥+用户密码的方式存在安全隐患:只要两个不同的超长密码前72位相同,就会被判定为有效密码,相当于削弱了密码的唯一性。
正确的解决方案
不要直接拼接密钥和密码,改用HMAC算法先对用户密码做带密钥的摘要处理,再进行哈希存储:
// 注册流程:生成带密钥的哈希存储 $user_pass = '用户输入的原始密码'; $secret_key = '你的Blowfish密钥'; // 用HMAC生成安全的带密钥摘要(true返回二进制原始数据,提升哈希效率) $hmac_result = hash_hmac('sha256', $user_pass, $secret_key, true); // 对HMAC结果进行密码哈希 $stored_hash = password_hash($hmac_result, PASSWORD_DEFAULT); // 登录验证流程 $input_pass = '用户登录输入的密码'; $input_hmac = hash_hmac('sha256', $input_pass, $secret_key, true); if (password_verify($input_hmac, $stored_hash)) { var_dump(true); // 验证通过 } else { echo "false"; }
HMAC会通过安全的密钥混合方式生成固定长度的摘要(比如SHA-256是32字节),既避开了Blowfish的72字符限制,又能保证不同密码(哪怕超长)生成的摘要唯一,安全性更有保障。
补充:password_hash使用的Blowfish系列算法($2a$/$2y$)的72字符限制是算法本身的设计特性,超出部分会被直接忽略,这是官方文档明确标注的细节。
内容的提问来源于stack exchange,提问作者marcfunk
相关产品推荐
相关产品推荐

