Php 为什么不应该';t我在crypt()函数中使用第23个字符';这是盐吗?

Php 为什么不应该';t我在crypt()函数中使用第23个字符';这是盐吗?,php,encryption,crypt,Php,Encryption,Crypt,我正在学习PHP的crypt()函数,并用它运行了一些测试。根据我的建议,我应该使用22个字符长的盐。但是,我可以使用23个字符长的字符串,但有一些限制。当我使用22个字符长的字符串时,我总是得到一个结果“$2y$xxStringStri.hashhas”。我知道这个时期只是盐的一部分 似乎如果我使用23个字符而不是22个字符,我就可以成功地生成不同的哈希,但是对于所有64个字符,只有4个不同的结果。第23个字符“向下舍入”至64个字符字母表中最接近的1/4(例如,第23个字符为“W”,向下舍入

我正在学习PHP的crypt()函数,并用它运行了一些测试。根据我的建议,我应该使用22个字符长的盐。但是,我可以使用23个字符长的字符串,但有一些限制。当我使用22个字符长的字符串时,我总是得到一个结果“$2y$xxStringStri.hashhas”。我知道这个时期只是盐的一部分

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

所有这四个密码函数都生成相同的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中是否存在一些不使用它应该避免的故障行为

关于我是如何计算salt中第23个字符的说明:

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

这与哈希冲突有关。一旦超过22个字符,生成的哈希就不再是唯一的,这取决于算法的
名称空间
。换句话说,超过22个字符不会导致任何安全性的提高,实际上会降低您的安全级别。

$不是实际salt的一部分。它是一个分离器


对于河豚穴,格式为$2[axy]$log2Rounds$[salt][hash]。你把它描述成加了一个那是因为您缺少最后一个字符。河豚的盐是128比特。你可以只使用126,是的,但你只是不必要地削弱了盐。

在我看来,它似乎增加了2点安全性。我仍然可以通过改变salt中的其他字符来生成不同的散列,同时将第23个字符保留为,比如说“a”。有没有关于盐溢出来的文章?即使是在网络上,他们也会使用一个超过22个字符的salt示例。当然,它会生成不同的结果,但如果使用23个字符,则会有另一个字符串产生完全相同的散列。这就是所谓的碰撞,当你试图保持每件事的独特性时,你不希望发生碰撞。嗯。。。。我不知道如何解释这一点,但我可以向您保证,在salt中使用23个字符(即使像您所说的那样存在salt冲突)比使用22个字符更安全。说明:假设我们有一种较小的河豚。在这个迷你鲍鱼中,我们可以放入1个字符长的盐,例如“a”或“4”或“I”。在开始盐碰撞之前,我们可以用它进行64种不同的组合。然而,我们可以再添加2位(“.”、“O”、“e”和“u”),并将64个唯一盐的组合转换为256个。即使没有完整的字母表,它也更安全。@Andrew:如果没有彩虹表,你说的是真的。彩虹表正是您不希望碰撞的原因。您是否能理解,拥有两个(或更多)将生成完全相同的哈希的字符串将使中断单向加密所需的时间减少2倍或更多?$不是salt的一部分。一旦你真的超过22个字符,它就不再是salt的一部分了。关于这个问题有一个很好的解释:谢谢你的回答。尽管这只解决了第23个字符的问题,因为由于crypt()函数中允许的位的大小,它只会被缩短。我的问题,用另一种方式问,是“即使第23个字符会被切分为两位,我也应该使用它吗?”或者另一种方式是“PHP的算法中是否有一个小故障,每当使用第23个字符时都会生成不正确的哈希?”顺便说一句,如果你实际上使用了太多的字符,那么你完全可以使用crypt()因为它被设计为用作crypt的crypt(password,salt),cryptedPassword==crypt(password,cryptedPassword)进行验证,它通过在输出时将哈希附加到salt,在输入时只使用相关的salt字节来实现这一点。所以你看,额外的字符是不会被使用的。
crypt('Test123','$2y$08$ABCDEFGHIJKLMNOPQRSTUV');
//        The salt is '$ABCDEFGHIJKLMNOPQRSTUV'
//        Which will be treated as '$ABCDEFGHIJKLMNOPQRSTUO'