我的登录系统遇到了一些问题。如果我将用户密码设置为"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问题
非常感谢您的帮助。
要使用crypt(),您必须遵守手册中列出的算法salt格式之一。您没有遵循其中一种格式,因此PHP将您的salt减少到前两个字符,并使用DES算法进行计算。DES只使用前8个字符,因此您只能用相同的salt对"TestPass"进行两次哈希处理。
最好使用password_hash()。但是,正如您所提到的,您的主机不支持password_hash()。
如果crypt()是最终选择,则需要正确格式化salt。然而,crypt()的最佳算法只允许salt最多包含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的PHP安装太旧,不适合任何像样的实现。我强烈建议找一个支持更高版本的服务器。我希望我的例子能帮助到你或其他人,以及由于原始密码相似性而进行的推理。