You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:12:27