为何binary(64)存储的60位密码哈希导出带4个\0?password_verify需截断?
这两个问题其实都和数据库字段类型的特性以及bcrypt哈希的标准规则有关,我来给你拆解清楚:
为什么导出的哈希末尾有4个\0?
- 首先,bcrypt生成的密码哈希固定是60个字符(包含
$2y$前缀和后续的哈希内容)。 - 你使用的
binary(64)是固定长度的二进制类型:如果存储的内容长度小于字段定义的64字节,数据库会自动用**空字节(\0)**填充到指定长度。64-60=4,这就是末尾4个\0的来源。 - phpMyAdmin在显示时会自动忽略字符串末尾的空字节(毕竟多数编程语言里
\0是字符串结束符),所以你看到的是60个字符的有效哈希,但导出时会完整输出字段内的所有内容,包括填充的空字节。
为什么必须截取前60个字符才能让password_verify正常工作?
- PHP的
password_verify()函数是严格遵循bcrypt哈希标准的,它只识别60个字符长度的bcrypt哈希串。 - 当你把带4个
\0的完整字段内容传给函数时,它会把整个64字节的内容当成哈希的一部分,而bcrypt的验证逻辑无法识别包含空字节的非标准长度哈希,自然验证失败。 - 用
substr($result, 0, 60)截取前60位,本质是去掉数据库自动填充的空字节,还原了bcrypt哈希的原始有效长度,这样password_verify就能正确识别并完成验证。
额外优化建议
其实更稳妥的做法是把数据库字段类型改成CHAR(60)或者VARCHAR(60):
CHAR(60)是固定长度的字符类型,刚好匹配bcrypt哈希的长度,不会产生填充问题;VARCHAR(60)是可变长度类型,也能完美存储60字符的哈希,避免后续还要手动截取的麻烦。
内容的提问来源于stack exchange,提问作者Mini
相关产品推荐
相关产品推荐

