理想的密码哈希算法是什么样的?

时间:2011-10-28 09:27:59

标签: hash passwords md5 sha1

免责声明:关于SO有很多类似的问题,但我正在寻找一个实用的建议而不仅仅是一般原则。另外,请随意指出“理想”算法的实现(PHP会很好;)但请提供具体信息(如何工作)。

计算用于存储在数据库中的密码的哈希字符串的最佳方法是什么?我知道我应该:

我在考虑使用这样的算法:

x = md5( salt + password);
repeat N-times:
    x = md5( salt + password + x );

我确信这是非常安全的,但有几个问题浮现在脑海中:

  1. 在salt中包含用户名是否有用?

  2. 我已经决定为所有用户使用普通盐,这有什么缺点吗?

  3. 建议的最小盐长度是多少?

  4. 我应该使用md5,sha还是别的什么?

  5. 上述算法/任何建议有什么问题吗?

  6. ...(随意提供更多信息:)

  7. 我知道决定必然取决于具体情况,但我正在寻找一个解决方案:

    • 提供尽可能多的安全性
    • 足够快(在体面的机器上<0.5秒)

    那么,理想的算法会是什么样的,最好是伪代码?

2 个答案:

答案 0 :(得分:6)

目前,“理想”密码哈希函数为bcrypt。它包括盐处理和可配置的迭代次数。有free opensource PHP implementation

第二好的是PBKDF2,它依赖于底层哈希函数,有点类似于你的建议。有technical reasons为什么bcrypt比PBKDF2“更好”。


至于你的具体问题:

  

1。在盐中包含用户名是否有益?

不是。

  

2。我已经决定为所有用户使用普通盐,这有什么缺点吗?

是的:它消除了加盐的好处。盐的唯一理由是每个散列密码都是唯一的。这可以防止攻击者攻击两个散列密码,而不是攻击一个散列密码的两倍。盐必须唯一。即使每个用户使用盐也很糟糕:当用户更改密码时,也必须更改salt。当盐被重用/共享时,攻击者可能应用的优化类型包括(但不限于)预先计算的哈希表,例如rainbow tables

  

3。建议的最小盐长度是多少?

盐必须是独一无二的。独特性是一项难以维护的特性。但是通过使用足够长的随机盐(使用良好的随机数生成器生成,最好是加密强的生成器),您可以获得具有足够高概率的唯一性。 128位盐足够长。

  

4。我应该使用md5,sha还是别的什么?

MD5对公共关系不利。它已知已知的弱点,可能适用于或不适用于给定的用法,并且很难用任何可靠性来“证明”这些弱点不适用于特定情况。 SHA-1更好,但不是“好”,因为它也有弱点,尽管不如MD5那么严重。 SHA-256是一个合理的选择。正如上面所指出的,对于密码散列,你需要一个在并行体系结构上很好地扩展的函数,例如GPU,并且SHA-256可以很好地扩展,这就是为什么Blowfish- bcrypt中使用的衍生物是优选的。

  

5。上述算法/任何建议有什么问题吗?

这是自制的。那很糟。麻烦的是,没有已知的加密算法安全性测试。我们可以期待的最好的事情就是让几百名专业的密码学家试图破解算法几年 - 如果他们不能,那么我们可以说虽然算法并没有真正“证明”是安全的,但至少是弱点一定不能显而易见。 Bcrypt已经存在,广泛部署并分析了12年。即使在StackOverflow的帮助下,你也无法独自击败它。

作为一名专业的密码学家,我会在MD5甚至SHA-256中使用简单的连接引起一个可疑的眉毛:这些是Merkle–Damgård哈希函数,这对于抗冲突性能很好,但是没有提供random oracle(有所谓的“长度延长攻击”)。在PBKDF2中,哈希函数不是直接使用,而是通过HMAC

答案 1 :(得分:1)

我倾向于使用固定的应用程序盐,用户名和密码

示例...

string prehash = "mysaltvalue" + "myusername" + "mypassword";

这里的好处是,使用相同密码的人最终没有相同的哈希值,并且它阻止有权访问数据库的人将密码复制到其他用户 - 当然,如果你可以访问数据库你不需要破解登录来获取数据;)

IMO,盐长度无关紧要,散列值长度总是为32(使用MD5 - 这也是我会用的)

我会说在安全性方面,这种密码加密就足够了,最重要的是要确保你的应用程序/数据库没有安全漏洞!

另外,我不打算反复哈希,我认为没有意义。有人必须知道你的算法试图以那种方式破解它然后无论是一次还是多次散列都没关系,如果他们知道它,他们知道它