我遇到了登录系统的一些问题。如果我将用户密码设置为' TestPassword1234',TestPassword'将被接受为密码。
经过测试后,我发现以下代码将导致创建两个相同的哈希值,即使传递的字符串不是相同的。
重要的是要知道所有使用的盐都是由这种功能产生的。每个测试生成一个,同一个用于散列两个字符串(就像登录用户时一样)。
function GUID() {
if (function_exists('com_create_guid') === true) { return trim(com_create_guid(), '{}'); }
return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}
上面的函数来自堆栈溢出问题,我不确定是哪个。
如果密码从根本上改变,则不是这种情况,请参阅下面的测试。
以下代码段显示两个不同的密码,产生相同的哈希值。
$guid = GUID();
echo( crypt("TestPassword1234", $guid ) ); //455nKS7NToPuY
echo("<br />");
echo( crypt("TestPassword", $guid ) ); //455nKS7NToPuY (the same!)
此代码段显示两个不同的密码,但不会产生相同的结果,即使它们遵循与上述代码段相似的模式
$guid = GUID();
echo( crypt("Test1234", $guid ) ); //BBWxwWzIXAOQI
echo("<br />");
echo( crypt("Test", $guid ) ); //BBhe4TjDcO5XA (different...)
我认为问题源于GUID函数的使用。可能是有问题或仅支持最大长度为x
的密码。我不知道,也无法追查我发现它的SO问题。
非常感谢帮助。
答案 0 :(得分:3)
要使用crypt(),您必须遵守手册中列出的算法盐格式之一。您没有遵循其中一种格式,因此PHP会将您的盐减少到前两个字符,并使用DES算法进行计算。 DES仅使用前8个字符,因此您只需要散列&#34; TestPass&#34;用同样的盐两次。
更好的办法是改用password_hash()。但是,正如您所提到的,您的主机不支持password_hash()。
如果crypt()是最终选择,那么您需要正确格式化盐。但是,使用crypt()进行选择的最佳算法仅允许盐最多16个字符。因此,使用GUID不是最佳选择,因为大多数数据未被使用。
以下是使用安全随机字节生成器的示例,这仅适用于PHP 5.3.2及更高版本:
function newSalt() {
$salt = bin2hex(openssl_random_pseudo_bytes (8));
return '$5$'.$salt;
}
$salt1 = newSalt();
$salt2 = newSalt();
echo( crypt("TestPassword1234", $salt1 ) );
echo("<br />");
echo( crypt("TestPassword", $salt2 ) );
您可以通过存储从newSalt()
生成的值来存储盐以供日后使用编辑:对于任何体面的实施,OP的安装都太旧了。我强烈建议找一个支持更高版本的服务器。我希望我的例子可以帮助你或其他人,以及由于原始密码的相似性而导致的推理。