这篇文章可能会偏离你最初的问题,但我希望你会发现它有用;
安全性是通过提高障碍和防御深度来实现的。没有真正安全的哈希解决方案,只有难以破解的解决方案。就像在你的房子里安装防盗警报器和窗户锁一样,使你的网站比别人的更不容易被攻破。
对于加密算法的盐只是安全问题的一个小部分。单个盐意味着在尝试破解多个用户的密码时少了一件事情要考虑。低熵盐(如服务器的时间)使得破解变得更难,而高熵盐使得破解更加困难。使用哪种盐,以及是否需要主要关注这一点,取决于你正在保护的数据的敏感性,以及你采取的其他安全措施。一个只为选定城市提供个性化天气预报的网站显然比一个具有你家地址、母亲的婚姓、出生日期和其他可用于身份识别目的的信息的网站具有更少的敏感数据。
所以这就是问题所在;即使是高熵盐,如果很容易获得,仍然是一个糟糕的盐。
在现实世界中,将盐存储在数据库中(随机或非随机)可能比使用常量盐并将其埋藏在无法通过网络浏览器访问的文件中不太安全。虽然唯一和高熵的盐更难猜测,但如果你允许从任何服务器上的MySql进行root登录,并将密码设置为“password”,那么这并不重要!对比一下破解数据库和获取有效登录到你的服务器有多容易——这可能更难以隐蔽地做到,因为你可以根据你的设置放置fail2ban和大量其他攻击向量监视器。
你可以通过在数据库中存储包含用户特定盐的文件位置而不是盐本身来结合这两种方法。是否需要破解文件系统和数据库取决于你试图保护的数据的敏感性是否需要这种开销。
安全专家的另一个替代建议是将用户名存储在与密码不同的数据库(最好是不同的技术)中,并使用UUID之间的引用。例如同时使用MySQL和SQLite。这意味着必须破解两个数据库(也是为什么,为了举例说明,你不应该在同一个数据库中存储用户详细信息和信用卡号码,因为一个没有另一个就没有用)。
请注意,像SHA-512和Blowfish这样的算法可以作为它们的哈希的一部分返回盐。对于这些算法要小心,因为如果你存储完整的哈希值,你就泄露了算法,这意味着黑客需要破解的东西就少了两个(盐也暴露了算法)。
确保强制使用强密码和用户名,这样字典攻击将会失败;我知道有针对MD5的所有6个字母数字组合的用户名/密码条目的字典,我怀疑还有更多的字典可用于各种算法。随着低成本云计算和CPGPU计算的爆炸式增长,可用字典的大小和复杂性将会爆炸。
最安全的方法是从不以编程方式生成盐,而是要求用户在 SSL 链接上输入它们的用户名和密码(因此无法被窃听),但从不存储它。这是信用卡公司采取的方法;即您在每次在线购买时都必须输入的 3 位 CSV 安全密钥,因为它不应存储在任何数据库中。如果您真的想生成盐,请将其单独发送给他们(例如通过 SMS 消息或电子邮件),并仍然让他们每次手动输入。采用这种方法虽然更安全,但需要权衡复杂性与用户是否会因为您使网站过于复杂而停止使用它。
所有以上内容仍然依赖于您是否还有防止会话劫持、跨站点脚本等保护措施。世界上最强大的密码算法是无关紧要的,如果我只需要计算一个已登录用户的有效 PHPSESSID 并劫持它!
我不是安全专家,但已经尽力阅读了很多相关内容。有这么多关于此主题的书籍表明您的问题的答案非常庞大。
以下是一些非常棒的书籍,您可能会喜欢尝试,我发现它们非常有价值:
《Web 应用程序漏洞检测、利用、预防》- ISBN-13: 978-1-59749-209-6
《使用 Apache 防止 Web 攻击》- ISBN-13: 978-0-321-32128-2
mt_rand
不是密码学强度,但它会给你比time
更多的“随机性”。PHP目前没有提供一种获取密码学强度随机数的方法(但正在研究中)。所以你应该要么坚持使用mt_rand
,要么分叉/dev/(u)random
。 - NikiC