为什么PHP crypt()将salt添加到哈希?

JD *_*cks 11 php security encryption hash

我正在研究构建一个登录系统,当你将2位数的盐传递给crypt()函数时,读取php手册后,它返回一个哈希字符串,字符串的前两位是你使用的盐.

例:

$salt = "kr";
echo crypt("mysecret",$salt); //returns "kreOI.F7eOQMY"
Run Code Online (Sandbox Code Playgroud)

我的第一个想法是,这不会帮助那些试图扭转你的哈希的人吗?

我在维基百科上查了一下说:

为了最好的安全性,盐值保密.

所以我不明白为什么crypt函数会返回所有使用salt值的哈希值?

是否有一个原因?这应该是一个安全问题吗?

eri*_*son 29

维基百科文章的作者将盐与搜索空间的概念混为一谈,暗示盐是一种阻止暴力攻击的方法.混淆这些想法并没有改善安全性; 无法识别和描述这两个问题的人不是一个可靠的指南.

salt的目的是阻止预先计算的查找表(如Rainbow表).Salt可以防止攻击者在"时间"内交换"空间".每一点盐都会使表的存储要求翻倍; 两个字节的盐会产生很大的(65536倍)差异,但是八个字节需要不存在的"yottabyte"存储设备用于查找表.

盐必须存放在某处.如果你有一个有效的方法来保持"秘密",为什么不用它来存储密码而忘记完全散列?没有; 如果你想要真正的安全性,你需要将系统设计为免受强力攻击,即使攻击者知道盐.该文假设盐可以保密,应视为虚假.

密钥加强(应用哈希函数数千次)和密码选择规则(最小长度,数字,特殊字符)可以最好地防止暴力攻击.

假设盐不能保密,鼓励更好的密钥加强和密码选择,这导致更安全的系统.


nuc*_*cc1 9

我应该评论Crypt没有Marc B听起来那么糟糕,并且实际上可能是获得良好哈希的最简单方法,只要你不依赖于像MD5这样的弱势方案.

看到:

如何在PHP中使用bcrypt进行散列密码?

http://uk.php.net/manual/en/function.crypt.php

http://www.openwall.com/phpass/


Mar*_*c B 1

crypt() 函数已过时。在影子密码支持出现之前,它被用来对旧式 Unix 系统的密码进行哈希处理。盐的存在是为了增加暴力破解密码的复杂性。然而,由于盐是由密码子系统随机生成的,因此它必须以明文形式存储,以便将来的任何密码操作都可以工作。如果在加密之前将盐嵌入到密码中,则没有实际的方法来验证密码 - 每当完成密码检查时,您都必须尝试每种可能的盐 - 非常不切实际。因此,盐被添加到加密密码的前面,这样您就可以再次将其取出以供将来使用。

crypted password: xxabcdefghijklmn
                  ^^- salt
                    ^^^^^^^^^^^^^^-- crypted pw

if ('xx' + crypt('xx' + password) == 'crypted string') then
     password is ok
endif
Run Code Online (Sandbox Code Playgroud)

如今,crypt() 的安全性等同于麦片盒解码器环。出于历史目的和低安全性“谁在乎它是否被破解”存储。对于任何现代密码的使用,您最好使用更现代的哈希值,例如 sha1/sha256/md5。如今,即使 md5 被认为已损坏,sha1 边缘也有裂缝,并且(我上次检查)sha256 仍然是安全的。

  • crypt() 并不是“过时的”——当然,旧的基于 DES 的哈希值在这一点上是可疑的,但是 MD5、Blowfish 和(在较新的 PHP 中)基于 SHA 的哈希值对于现代密码哈希来说工作得很好。 (19认同)
  • 盐“不是”用来增加暴力破解的复杂性。它的存在是为了防止彩虹表的时空权衡。 (6认同)