PHP的PASSWORD_DEFAULT哈希算法为何仅验证前8位字符?
问题解答
1. 如何实现完整密码的哈希?
绝对不要手动拼接盐值和密码,password_hash()会自动生成安全的盐值并嵌入最终的哈希字符串中,正确用法是直接传入明文密码:
<?php $test_pw = "%ImAVery1234Secure!Password$"; $password_hashed = password_hash($test_pw, PASSWORD_DEFAULT); echo password_verify($test_pw, $password_hashed); // 返回1 ?>
你遇到的前8位验证通过的问题,是因为PASSWORD_DEFAULT默认采用的bcrypt算法,最多只处理输入字符串的前72字节——你手动拼接盐值后,前72字节刚好包含盐+前8位密码,导致验证通过。如果使用PHP 7.4及以上版本,PASSWORD_DEFAULT会自动切换为Argon2id算法,该算法没有72字节的输入限制,能完整处理任意长度的密码。
2. 是否必须更换哈希算法?
不需要强制更换,但推荐在PHP版本支持(PHP 7.2+)的情况下,使用PASSWORD_ARGON2ID作为哈希算法,它的安全性比bcrypt更高,且无输入长度限制。
3. 更换算法后,能否使用password_verify验证?
完全可以!password_verify()会自动识别哈希字符串对应的算法,不管是bcrypt、Argon2i还是Argon2id,只要是password_hash()生成的哈希,都能直接用它验证。
绝对不要用password_hash(...) == $db_password这种写法,这种方式会失去哈希算法的自适应特性,还存在时序攻击的风险,password_verify()已经帮你规避了这些安全问题。
4. 现有已哈希的密码能否重新哈希?
不能直接对已哈希的密码重新哈希(哈希是单向不可逆的,无法还原明文),只能在用户下次登录时,获取到用户输入的明文密码,验证旧哈希通过后,再用新算法重新哈希并更新数据库中的记录。示例代码如下:
<?php // 用户输入的明文密码 $user_input_pw = $_POST['password']; // 从数据库取出旧哈希 $old_hash = $db->query("SELECT password FROM users WHERE id = ?", [$user_id])->fetchColumn(); if (password_verify($user_input_pw, $old_hash)) { // 验证通过,检查当前哈希是否为推荐算法 $hash_info = password_get_info($old_hash); if ($hash_info['algoName'] !== 'argon2id') { // 用新算法重新哈希并更新数据库 $new_hash = password_hash($user_input_pw, PASSWORD_ARGON2ID); $db->query("UPDATE users SET password = ? WHERE id = ?", [$new_hash, $user_id]); } // 登录成功逻辑 } else { // 密码错误逻辑 } ?>
内容的提问来源于stack exchange,提问作者CuzImBisonratte
相关产品推荐
相关产品推荐

