crypt($pass,';$2y$09$salt';)==crypt($pass,crypt($pass,';$2y$09$salt';)在PHP中是如何实现的?

crypt($pass,';$2y$09$salt';)==crypt($pass,crypt($pass,';$2y$09$salt';)在PHP中是如何实现的?,php,hash,blowfish,crypt,Php,Hash,Blowfish,Crypt,我对crypt()PHP函数非常困惑 当第二个crypt显然使用不同的第二个参数时,以下两个crypt函数如何给出相同的输出?不同的盐意味着不同的散列,对吗 echo crypt("password", '$2y$09$anexamplestringforsalt$')."\n<br>"; echo crypt("password", crypt("password", '$2y$09$anexamplestringforsalt$'))."\n<br>"; 原因是sa

我对crypt()PHP函数非常困惑

当第二个crypt显然使用不同的第二个参数时,以下两个crypt函数如何给出相同的输出?不同的盐意味着不同的散列,对吗

echo crypt("password", '$2y$09$anexamplestringforsalt$')."\n<br>";
echo crypt("password", crypt("password", '$2y$09$anexamplestringforsalt$'))."\n<br>";

原因是salt是crypt提供的散列输出的一部分

$2y$09$anexamplestringforsale/.K.VdgECUVEd9N4ja3u1WtgPi5BXZq 
分为几个部分:

  • 2y
    -算法标识符(bcrypt)
  • 09
    -成本参数
  • anexamplestringforsale
    -盐
  • /.K.VdgECUVEd9N4ja3u1WtgPi5BXZq
    -散列
这就产生了一个很好的特性,就是能够在验证调用中将结果散列直接用作salt

$hash = crypt($password, $salt);

if ($hash === crypt($password, $hash)) {
现在,您不需要单独存储算法、成本或盐。直接将它们存储在散列结果中。简单


另外,我强烈建议您使用简化的密码哈希API,该API专门用于缓解这些问题:。

如果您使用BlowFish算法,您的代码将最终运行到此函数:(源代码)

宣言:

static char *BF_crypt(const char *key, const char *setting,
char *output, int size,
BF_word min)
密钥是$str,设置是php函数的$salt
string crypt(string$str[,string$salt])
,输出将是加密的返回值

正如您在源代码中看到的:

首先,在第777行,
memcpy(输出,设置,7+22-1)
,此行将$salt的前29个字符(从位置0到位置7+22-1)复制到返回值中,返回值为
$2y$09$anexamplestringforsale

其次,剩下的$salt从未被使用过

第三,在第784行,
BF_编码(&output[7+22],data.binary.output,23),将加密字符串附加到返回值上


因此,$str和$salt的前29个字符是影响您返回值的因素。

谢谢您提供的信息,Max.Voting up。非常感谢!这很有帮助。所以基本上,crypt函数分解$hash字符串,并使用子字符串(salt部分)作为实际的salt?正确。它实际上使用了除散列部分之外的所有片段。如果您使用我链接到的简化密码散列API,
password\u verify()
也会使用散列部分为您验证散列。简而言之,如果你直接制造盐,或者直接使用crypt,你很可能做错了什么。
static char *BF_crypt(const char *key, const char *setting,
char *output, int size,
BF_word min)