2013-03-05 46 views
9

我正在学习PHP的crypt()函数,并且一直在运行一些测试。根据this post,我应该使用22个字符长的盐。但是,我可以使用长度为23个字符的字符串,但有一些限制。当我使用长度为22个字符的字符串时,我总是得到'$ 2y $ xxStringStringStringStri.HashHashHashHashHashHashHashHas'的结果。我知道这个时期只是盐的一部分。为什么我不应该在crypt()函数的盐中使用第23个字符?

看来,如果我使用23个字符而不是22个字符,我可以成功生成不同的哈希值,但对于所有64个字符只有4种不同的结果。第23位字符“向下取整”到64个字符的字母的最接近的1/4(例如第23位字符是“W”和向下取整为“O”或任何数量的向下取整为“U”)

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

这些隐窝功能全部四生成相同的盐:

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' 
+1

关于这个问题有一个很好的解释:http://security.stackexchange.com/questions/20862/php-crypt-trims-the-salt-as-it-would-be-too-long – 2013-03-05 16:53:06

+0

谢谢你这个回应。虽然这只能解决第23个字符所发生的情况,因为它只会因crypt()函数中允许的位的大小而缩短。另外一个问题,我的问题是“即使将它切成两位,我是否应该使用第23个字符?”或者另一种方式是“每当使用第23个字符时,PHP算法中是否会产生错误的哈希?” – Andrew 2013-03-05 17:11:22

回答

2

它与哈希冲突的事情。一旦超过22个字符,根据算法的NAMESPACE,生成的散列不再是唯一的。换句话说,超过22个字符不会导致任何增加的安全性,并且实际上可以降低您的安全级别。

+1

在我看来,它增加了2个安全位。我仍然可以通过改变整个盐中的其他字符而产生不同的哈希值,而将第23个字符作为,让我们说“a”。有没有关于溢出盐的文章?即使在[php.net](http://php.net/manual/en/function.crypt.php)上,他们也会使用超过22个字符的salt示例。 – Andrew 2013-03-05 16:51:22

+1

当然,它会产生不同的结果,但如果你使用23个字符,那么会有另一个字符串,这将导致完全相同的散列。这就是所谓的碰撞,当你试图让所有东西都保持独特时,你并不希望这样做。 – 2013-03-05 16:53:03

+0

嗯....我不知道如何解释这一点,但我可以保证你在盐中使用23个字符(即使有像你说的盐碰撞)比使用22更安全。解释:让我们说我们有一种小型河豚。在这个迷你蝴蝶鱼中,我们可以放入1个字符长度的盐,如“a”或“4”或“I”。在我们开始得到盐碰撞之前,我们可以用它来做出64种不同的组合。但是,我们可以只添加2个位(“。”,“O”,“e”和“u”),并将64个独特盐的组合变为256.即使不是全字母,它也更安全。 – Andrew 2013-03-05 16:58:34

0

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

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

+0

如果你真的使用了太多的字符,顺便说一句,你用crypt()完全没问题,因为它被设计用作crypt的密码(密码,salt),cryptedPassword == crypt(password,cryptedPassword)用于验证,它通过将散列附加到输出中的salt来完成此操作,并且仅在输入上使用相关的盐字节。所以你看,额外的字符不会被使用。 – Zer 2013-05-10 15:15:36

相关问题