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

时间:2013-03-05 16:39:33

标签: php encryption crypt

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

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

v---------------v---------------v---------------v---------------
./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890

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

crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAq');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAr');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAs');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAt');

但这个是不同的:

crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAu');

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

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

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

2 个答案:

答案 0 :(得分:2)

它与哈希冲突有关。一旦超过22个字符,生成的哈希值就不再是唯一的,具体取决于算法的NAMESPACE。换句话说,超过22个字符不会导致任何安全性增加,实际上会降低您的安全级别。

答案 1 :(得分:0)

$不是实际盐的一部分。它是一个分隔符。

对于Blowfish crypt,格式为$ 2 [axy] $ log2Rounds $ [salt] [hash]。你描述它添加一个。 - 那是因为你错过了最后一个角色。 Blowfish的盐是128位。你只能使用126,是的,但你只是不必要地削弱了盐。