为什么我不应该在crypt()函数的salt中使用第23个字符?

And*_*rew 9 php encryption crypt

我正在学习PHP的crypt()函数,并且已经用它运行了一些测试.根据这篇文章,我应该使用长度为22个字符的盐.但是,我可以使用长度为23个字符的字符串,但有一些限制.当我使用22个字符长的字符串时,我总是得到'$ 2y $ xxStringStringStringStri.HashHashHashHashHashHashHashHas'的结果.我知道这个时期只是盐的一部分.

似乎如果我使用23个字符而不是22个字符,我可以成功生成不同的哈希值,但所有64个字符只有4种不同的结果.第23个字符"向下舍入"到64字符字母表中最接近的1/4(例如,第23个字符为"W"并向下舍入为"O"或任何数字向下舍入为"u")

v---------------v---------------v---------------v---------------
./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890
Run Code Online (Sandbox Code Playgroud)

所有这四个crypt函数都生成相同的salt:

crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAq');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAr');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAs');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAt');
Run Code Online (Sandbox Code Playgroud)

但这个是不同的:

crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAu');
Run Code Online (Sandbox Code Playgroud)

那么为什么我不能使用第23个字符才能成功产生不同的结果呢?在PHP中是否存在一些应该通过不使用它来避免的错误行为?

为了澄清我如何计算盐中的第23个字符:

crypt('Test123','$2y$08$ABCDEFGHIJKLMNOPQRSTUV');
//        The salt is '$ABCDEFGHIJKLMNOPQRSTUV'
//        Which will be treated as '$ABCDEFGHIJKLMNOPQRSTUO'
Run Code Online (Sandbox Code Playgroud)

小智 2

它与哈希冲突有关。NAMESPACE一旦超过 22 个字符,根据算法的不同,您生成的哈希值将不再是唯一的。换句话说,超过 22 个字符不会提高安全性,实际上会降低安全级别。