是时候()好盐吗?

我正在看一些我自己写的代码。 代码尝试使用SHA512散列密码,并使用time()作为salt。 是time()太简单盐或为此代码安全吗?

感谢您的答复和评论。 我将在这里为新读者总结一下:

  • 每个用户的盐应该是不同的,所以如果两个用户同时注册,他们的盐将不是唯一的。 这是一个问题,但不是一个大问题。
  • 但盐不应该与用户有任何关系,所以time()不是一个好的盐。
  • 使用一种随机的,均匀分布的,高熵的盐。 ” – 这是一口,所以什么样的代码可能会产生一个random, evenly distributed, high entropy盐?

好的,那我怎么样用一个32字符长的随机stringreplacetime()。 随机string可以通过在一组字母字符上循环32次而生成。 这听起来不错吗?

简短的回答:

不, time()不是一个好盐。

很长的回答:

从我的答案复制到盐生成和开源软件

什么是盐?

salt是随机的一组固定长度的字节,添加到散列algorithm的input中。

为什么腌制(或播种)散列有用?

向散列添加一个随机盐可以确保相同的密码会产生许多不同的散列。 盐通常与散列函数的结果一起存储在数据库中。 抨击散列是有好处的一些原因:

  1. 盐化大大增加了预计算攻击的难度/成本(包括彩虹表 )
  2. Salting确保相同的密码不会导致相同的散列。 这确保您不能确定两个用户是否具有相同的密码。 而且, 更重要的是 ,您不能确定同一个人是否在不同的系统上使用相同的密码。
  3. 腌制增加了密码的复杂性,从而大大降低了 字典 生日攻击 的有效性 (这只有在盐与散列分开存储的情况下才是真实的)。
  4. 适当的腌制大大增加了预计算攻击的存储需求,直到它们不再实用。 (8字符区分大小写的字母数字密码与16位盐,哈希到128位值,将占用不超过200 艾字节,而不减less彩虹)。

盐不需要保密。

盐不是一个秘密密钥,而是通过使每个实例的散列函数具有特定的含义来工作。 使用盐腌散列,没有一个散列函数,但是对于每个可能的盐值。 这样可以防止攻击者攻击N个散列密码的次数小于N次攻击密码的成本。 这是盐的重点。
一个“秘密盐”不是一个盐,它被称为“钥匙”,这意味着你不再计算哈希,而是一个消息authentication码 (MAC)。 计算MAC是一项棘手的业务(比简单地将一个密钥和一个值集中到一个哈希函数中要复杂得多),而这完全是一个非常不同的主题。

对于使用它的每个实例,盐必须是随机的。 这确保了攻击者必须分别攻击每个腌制的散列。
如果你依赖于你的盐(或者腌制algorithm)是秘密的,你进入了默默无闻的安全领域(不起作用)。 最有可能的是,你没有从盐的保密中获得额外的安全保障。 你只是得到了温暖的模糊的安全感。 所以不是让你的系统更安全,而是把你从现实中分离出来。

那么,为什么盐必须是随机的呢?

从技术上讲,盐应该是独一无二的 。 对于每个哈希密码,盐的点是不同的。 这意味着全世界 。 由于没有中央组织根据需要分配独特的盐,所以我们不得不依靠下一个最好的事情,即随机select一个不可预测的随机生成器,最好在一个足够大的盐空间内使碰撞不可能发生(使用相同的两个实例盐值)。

试图从一些“大概是独一无二的”数据(例如用户ID)中推导出一个salt,但是这样的scheme往往因为一些令人讨厌的细节而失败:

  1. 例如,如果您使用用户标识 ,则某些攻击不同系统的坏人可能只是汇集资源并为用户标识1至50创build预先计算的表。用户标识是系统范围 唯一的,但不是全球范围的

  2. 这同样适用于用户名 :每个Unix系统有一个“root”,但世界上有很多根。 彩虹表“根”是值得的,因为它可以应用于数百万的系统。 更糟糕的是,还有很多“bob”,很多没有系统pipe理员的培训:密码可能相当薄弱。

  3. 唯一性也是暂时的。 有时用户更改密码。 对于每个新密码 ,必须select新的盐 。 否则,攻击者获得旧密码的散列,新散列可能试图同时攻击。

使用从密码安全,不可预知的PRNG获得的随机盐可能是某种矫枉过正的,但至less它可以保护你免受所有这些危害。 这并不是要阻止攻击者知道什么是一个单独的盐,而是为了不给他们一个大的,胖的目标,将用于大量的潜在目标。 随机select使得目标尽可能地薄。

结论是:

使用随机均匀分布的高熵盐。 每当您创build新密码或更改密码时,请使用新盐。 将盐与散列的密码一起存储。 赞成大盐(至less10个字节,最好16个或更多)。

盐不会把一个错误的密码变成一个好的密码。 它只是确保攻击者至less会支付他破解的每个密码的字典攻击价格。

有用的来源:
stackoverflow.com: 密码哈希的非随机盐
布鲁斯·施奈尔: 实用密码学 (书)
Matasano安全: 足够与彩虹桌
usenix.org: 自从1976年Unix密码使用盐
owasp.org : 为什么要加盐
openwall.com :

免责声明:
我不是安全专家。 (虽然这个答案由Thomas Pornin审查)
如果有任何安全专家发现有问题,请发表评论或编辑这个维基答案。

至于什么似乎是你的随机盐的好来源
另请阅读: 什么是随机数生成最安全的种子?
在没有专用的,基于硬件的随机生成器的情况下,获取随机数据的最好方法是询问操作系统(在Linux上,这称为/dev/random/dev/urandom都有优点和问题,毒];在Windows上,调用CryptGenRandom()

如果由于某种原因,你不能访问上面提到的随机源,你可以使用下面的函数:
来自phpass v0.3的源码

 <?php /** * Generate pseudo random bits * @copyright: public domain * @link http://www.openwall.com/phpass/ * @param int $length number of bits to generate * @return string A string with the hexadecimal number * @note don't try to improve this, you will likely just ruin it */ function random_bits($entropy) { $entropy /= 8; $state = uniqid(); $str = ''; for ($i = 0; $i < $entropy; $i += 16) { $state = md5(microtime().$state); $str .= md5($state, true); } $str = unpack('H*', substr($str, 0, $entropy)); // for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!? // so, added the substr return substr(str_pad($str[1], $entropy*2, '0'), 0, $entropy*2); } ?> 

更新

这不是一个很好的盐,但可能足以击败所有,但最坚定和足智多谋的攻击者。 一个好的盐的要求是:

  • 每个用户都不同
  • 足够长的时间(至less是字母数字8个字符)使得盐和(可能较弱)密码的连接太长以至于不能进行暴力破解。

time()值不够长,因为它们有10个字符,但只有数字。

另外,有时两个用户在同一秒内创build时可能会得到相同的值。 但是这只是一个问题,如果你有在同一秒内自动创build许多用户的情况。

在任何情况下,比完美盐更重要的是使用一个好的散列函数,而SHA512是我们现在可用的最好的之一。

这篇文章可能会偏离你原来的问题,但我希望你觉得它有用。

安全是关于提高障碍和障碍; 防御深入。 没有真正安全的哈希解决scheme,只是那些很难打破。 这就像在家里放入防盗报警器和窗户锁 – 让你的网站比别人的闯入吸引力小。

encryptionalgorithm的盐只是安全问题的一小部分。 单一的盐只是意味着当试图破解多个用户的密码时,还有一件事要弄清楚。 一个低熵盐(如服务器的时间)使得它有点困难,高熵盐使它更难。 要使用哪些内容,以及是否需要担心,主要取决于您所保护的数据的敏感性,以及您所采取的其他安全措施。 一个网站,只是提供了一个选定的城市个性化的天气预报,显然比那些有你的家庭地址,母亲的娘家姓,出生date和其他信息,可用于识别的敏感数据。

所以这里是磨擦 高熵盐如果容易获得,仍然是一种不好的盐。

在现实世界中,将盐存储在数据库中(随机或不随机)的安全性可能不如使用恒定盐的安全性,并且将其从私人的眼睛掩埋在通过networking浏览器无法访问的文件中。 虽然独特的高熵盐难以猜测,但是如果您已经允许从MySql上的任何服务器进行rootlogin并将密码设置为“密码”,那么这并不重要! Constrast破解数据库与获得有效的login到服务器是多么容易 – 这可能更难做到离散,因为您可以根据您的设置将fail2ban和其他攻击vector监视器放在适当位置。

您可以通过将包含用户特定的盐的文件的位置存储在数据库中而不是盐本身来组合这两种方法。 是否必须破解文件系统和数据库是否有保证取决于您尝试保护的数据的敏感性是否会造成这种开销。

另一种来自安全专家的build议是将用户名存储在一个单独的数据库中(并且理想情况下是不同的技术)密码,并使用UUID在两者之间进行引用。 比如同时使用MySQL和SQLite。 这意味着两个数据库都必须被破解(这也是为什么,为了举例说明,要单独放置一个兔子洞,不应该将用户的详细信息和信用卡号码存储在同一个数据库中,因为一个数据库是没有用的另一个)。

请注意,像SHA-512和Blowfish这样的algorithm可以将salt作为哈希的一部分返回。 要小心这些,就好像你存储了你给出algorithm的完整散列值,这意味着黑客找不到两件事(盐也给出algorithm)。

确保你执行强密码和用户名,所以字典攻击将失败; 我知道所有字母数字组合的MD5的用户名/密码条目的字典,我怀疑,有不止这些可用于各种algorithm。 随着低成本云计算和CPGPU计算的迅猛发展,可用字典的规模和复杂性将会爆炸性增长。

最终,最安全的方法是不要以编程方式生成盐,但需要用户通过SSL链接input用户名和密码(因此无法窥探),但从不存储它。 这是信用卡公司采用的方法; 即信用卡上的3位CSV安全密钥,每次在线购买时都必须input,因为它不应该存储在任何数据库中。 如果你真的想生成盐,分别发送给他们(例如通过短信或电子邮件),并仍然使他们每次都手动input。 通过这种方法,虽然更安全,但您需要将复杂性与用户是否停止使用该网站进行对比,因为您已经使用该网站难以为之。

以上所有依然是依靠这样一个事实,即对于会话劫持,跨站点脚本等等,您也具有保护。世界上最强大的密码algorithm是无关的,如果我只需要计算一个有效的PHPSESSIDlogin的用户并劫持它!

我不是一名安全专家,但是我已经尽可能多地阅读了这方面的内容。 关于这个问题有这么多书的事实表明你的问题的答案真的是多大。

你可能会喜欢尝试的几本非常棒的书,我发现它们是无价的;

Web应用程序漏洞检测,利用,预防 – ISBN-13:978-1-59749-209-6

使用Apache防止Web攻击 – ISBN-13:978-0-321-32128-2

不,时间()不是一个好盐

当谈到authentication时,最好不要重新发明轮子,而要回答你的问题, 。 时间问题():

  • 这是可预测的,它与可能发现的事物相关联。 这些问题使交叉匹配不同的哈希结果更容易。
  • 没有很多可能的价值。 由于高位不会改变,所以它比第一次出现的盐更窄。
  • 使用它重复以前的错误。 如果这个应用程序是一个使用time()作为盐的,至less它会需要一个新的攻击。

是。
看起来,一个unix时间戳,存储在用户数据库中作为“成员以来”字段将是体面的盐。

但是,盐问题是微不足道的。 还有更重要的事情你必须注意:

  1. 最有可能不是密码,盐或散列algorithm将成为您的网站最薄弱的部分。 一些跛脚文件注入或XSS或CSRF肯定是。 所以,不要做太多的事情。
    在典型的networking应用中,说一个32字符的真正的随机string,就像谈到木制谷仓里的32英寸装甲门。

  2. 说到密码, 最重要的是密码的复杂性。 用弱口令,没有盐和哈希algorithm,甚至超级巧妙的难以置信的硬件,都可以提供帮助。 要求用户使用复杂的密码是一件痛苦的事情,但如果没有它,所有的东西都会变成一堆废话。
    所以,你的第一个担心应该是密码的复杂性。 12-16个不同的字符,包括数字和标点符号是必需的。

  3. 至于盐, 我没有看到使用时间的好处,因为您必须将其与其他用户数据一起存储。 更好地使用电子邮件 – 这是足够随机的,你已经无论如何。 如果用户更改了电子邮件,请不要忘记重新密码。 似乎unix timstamp将是一个体面的盐,不需要使用电子邮件或其他任何东西。

更新
正如我所看到的,许多人仍然无法明白这一点。
就像那个人的评论一样,说

许多用户使用弱密码(我们应该教育他们,或者至less不断尝试),但这不是理由; 他们仍然应该得到很好的安全

毫无疑问,他们应该得到。 但是密码很弱的任务。 是。 不可能。

如果你的密码很弱,那么没有盐会保护它。

虽然盐在这个主题上花费10千字节的文本并不重要。

通过打破密码和预计算哈希之间的匹配,盐被用来防止彩虹攻击。 所以盐的主要任务是每个用户/密码logging不同。 只要不同用户的盐分不同,盐的随机化质量无关紧要。

一个成员join论坛/网站的date一般是公开访问的,这与time()相同,因此使你的盐无用。

没有! 切勿使用当前时间作为盐。 你可以在java中使用类似'SecureRandom'的东西来生成一个安全的随机盐。 始终使用不可预知的随机数作为盐。
使用时间作为盐可以帮助您在一定程度上消除冲突(因为两个用户可以同时提供相同的密码),但仍然可以恢复密码。

用户名应该足够了,也许注册时间戳,但是你应该把它存储在数据库的某个地方。 无论如何,你使用的每个值你的密码哈希值,应该以某种方式存储,所以你可以重新计算哈希值。

用户名+时间戳是否足够安全? 它应该是。 对于破解SHA512通常使用彩虹表。 一个用户名+时间戳应该是一个足够多的盐,所以没有办法在网上有一个彩虹表,它包含用这种方法腌过的密码的预先计算的散列。