为PHP密码提供安全散列和盐分

目前说MD5是部分不安全的。 考虑到这一点,我想知道使用哪种机制来保护密码。

这个问题,“双重散列”密码不仅仅是一次散列吗? 建议多次散列可能是一个好主意,而如何实现单个文件的密码保护? 建议使用盐。

我使用PHP。 我想要一个安全快速的密码加密系统。 散列密码一百万次可能更安全,但速度也更慢。 如何在速度和安全之间取得良好的平衡? 此外,我更喜欢结果有一个恒定数量的字符。

  • 哈希机制必须在PHP中可用
  • 它必须是安全的
  • 它可以使用盐(在这种情况下,所有的盐都是同样好的吗?有什么方法可以产生好的盐吗?)
  • 另外,我应该在数据库中存储两个字段(例如,使用MD5和使用SHA的另一个字段)? 它会使它更安全还是不安全?

    如果我不够清楚,我想知道使用哪个哈希函数以及如何选择一个好的盐,以便拥有一个安全快速的密码保护机制。

    不完全覆盖我的问题的相关问题:

    PHP和SHA中的MD5有什么区别
    简单的密码加密
    存储密钥的安全方法,用于asp.net的密码
    你将如何在Tomcat 5.5中实现咸味密码


    免责声明 :这个答案是在2008年写的。

    从那以后,PHP给了我们password_hashpassword_verify ,自推出以来,他们是推荐的密码散列和检查方法。

    尽管答案的理论仍然是一个很好的解读。

    TL; DR

    注意事项

  • 不要限制用户可以输入密码的字符。 只有白痴才能做到这一点。
  • 不要限制密码的长度。 如果你的用户想要一个带有supercalifragilisticexpialidocious的句子,不要阻止他们使用它。
  • 切勿以纯文本格式存储用户的密码。
  • 切勿将密码通过电子邮件发送给用户,除非他们丢失了密码,并且您发送了临时密码。
  • 永远不要以任何方式记录密码。
  • 永远不要使用SHA1或MD5甚至SHA256哈希密码! 现代饼干可分别超过60亿和1800亿次/秒(分别)。
  • 不要混合使用bcrypt和hash()的原始输出,要么使用十六进制输出,要么使用base64_encode。 (这适用于任何可能有恶意输入,这会严重削弱安全性。)
  • DOS

  • 尽可能使用scrypt; 如果你不行,就加密。
  • 如果您不能使用bcrypt或scrypt,并使用SHA2散列,请使用PBKDF2。
  • 数据库受损时重置每个人的密码。
  • 实现合理的8-10个字符的最小长度,并且至少需要1个大写字母,1个小写字母,一个数字和一个符号。 这将改善密码的熵,反过来使它更难以破解。 (请参阅“什么是一个很好的密码?”以进行一些辩论。)
  • 为什么要密码?

    哈希密码背后的目标很简单:通过妥协数据库来防止恶意访问用户帐户。 所以密码哈希的目标是通过花费太多时间或金钱来计算明文密码来阻止黑客或黑客。 时间/成本是你武库中最好的威慑力量。

    另一个需要在用户帐户上使用强大哈希的原因是为了让您有足够的时间来更改系统中的所有密码。 如果您的数据库被破坏,您将需要足够的时间至少锁定系统,如果不更改数据库中的每个密码。

    Whitehat Security首席技术官Jeremiah Grossman在最近密码恢复之后在博客中表示,要求强力破解密码保护:

    有趣的是,在这个噩梦中,我学到了很多我不知道密码破解,存储和复杂性的知识。 我明白为什么密码存储比密码复杂性更重要。 如果你不知道你的密码是如何存储的,那么你真正可以依赖的是复杂性。 这可能是密码和加密专家的常识,但对于普通的信息安全或网络安全专家,我非常怀疑它。

    (强调我的。)

    无论如何,什么使得一个好的密码?

    熵。 (并不是我完全赞同兰德尔的观点。)

    简而言之,熵是密码内多少变化。 当密码只有小写的罗马字母时,只有26个字符。 这并没有太大的变化。 字母数字密码更好,有36个字符。 但是,允许大写和小写的符号大约有96个字符。 这比字母好多了。 一个问题是,为了让我们的密码难忘,我们插入模式 - 这减少了熵。 哎呀!

    密码熵很容易估计。 使用全部ASCII字符(大约96个可键入的字符)会产生每个字符6.6的熵,对于未来的安全性,密码的8个字符仍然太低(熵为52.679位)。 但好消息是:更长的密码和带有unicode字符的密码确实会增加密码的熵并使其更难破解。

    Crypto StackExchange站点上有更长的密码熵讨论。 一个好的谷歌搜索也会带来很多结果。

    在我和@popnoodles谈到的评论中,他指出,通过使密码策略更易于预测,强制X长度的密码策略以及许多字母,数字,符号等实际上可以减少熵。 我同意。 Randomess尽可能真正随机,始终是最安全但最难忘的解决方案。

    据我所知,制作世界上最好的密码是Catch-22。 要么它不令人难忘,太可预测,太短,太多的unicode字符(很难在Windows / Mobile设备上键入),太长等等。没有密码对我们的目的来说足够好,所以我们必须像保护它们一样保护它们在诺克斯堡。

    最佳实践

    Bcrypt和scrypt是当前的最佳实践。 Scrypt会比bcrypt更好,但它并没有被Linux / Unix或网络服务器视为标准,并且还没有对其算法的深入评论。 但是,该算法的未来仍然看起来很有希望。 如果你正在使用Ruby,那么就有一个可以帮助你的scrypt gem,而Node.js现在有它自己的scrypt包。 您可以通过Scrypt扩展名或Libsodium扩展名在PHP中使用Scrypt(均可在PECL中使用)。

    如果你想了解如何使用bcrypt,或者发现自己是一个很好的包装器,或者使用类似PHPASS的东西来实现更多的传统实现,我强烈建议阅读crypt函数的文档。 我建议至少12轮bcrypt,如果不是15到18。

    当我知道bcrypt只使用blowfish的关键时间表和可变成本机制时,我改变了使用bcrypt的想法。 后者让你通过增加河豚已经很贵的关键时间表来增加强制密码的成本。

    平均做法

    我几乎无法想象这种情况了。 PHPASS支持PHP 3.0.18到5.3,所以它几乎可以在任何可以想象的安装上使用 - 如果您不确定您的环境是否支持bcrypt,则应该使用它。

    但是,假设你根本不能使用bcrypt或PHPASS。 然后怎样呢?

    尝试使用您的环境/应用程序/用户感知可以容忍的最大轮次数来实施PDKBF2。 我建议的最低数字是2500发。 另外,如果可以使用hash_hmac()来使操作难以重现,请确保使用它。

    未来的做法

    来自PHP 5.5的是一个完整的密码保护库,它可以抽象出使用bcrypt的任何痛苦。 尽管我们大多数人在大多数常见环境(尤其是共享主机)中都使用PHP 5.2和5.3,但@ircmaxell已经为将来与PHP 5.3.7兼容的API构建了兼容层。

    密码学概述和免责声明

    实际破解散列密码所需的计算能力不存在。 计算机“破解”密码的唯一方法是重新创建密码并模拟用于保护密码的散列算法。 哈希的速度与其被强制使用的能力呈线性关系。 更糟糕的是,大多数哈希算法可以很容易地并行执行得更快。 这就是为什么像bcrypt和scrypt这样昂贵的方案如此重要。

    你不可能预见攻击的所有威胁或途径,所以你必须保护用户前面你最大的努力。 如果你不这样做,那么你甚至可能会错过你遭到袭击的事实,直到它为时已晚......而你要承担责任。 为了避免这种情况,首先采取偏执行为。 攻击自己的软件(内部)并尝试窃取用户凭据,或修改其他用户的帐户或访问其数据。 如果你没有测试系统的安全性,那么除了你自己,你不能责怪任何人。

    最后:我不是密码学家。 无论我说的是我的意见,但我碰巧认为这是基于良好的常识......和大量的阅读。 请记住,尽可能地偏执狂,让事情尽可能闯入,然后,如果您仍然担心,请联系白帽黑客或密码专家,看看他们对您的代码/系统的看法。


    一个更短,更安全的答案 - 不要编写自己的密码机制 ,使用经过验证的机制。

  • PHP 5.5或更高版本:password_hash()质量好,是PHP核心的一部分。
  • 较老的PHP版本:OpenWall的phpass库比大多数自定义代码要好 - 用于WordPress,Drupal等。
  • 大多数程序员只是没有专业知识来安全地编写加密相关代码而不会引入漏洞。

    快速自检:什么是密码扩展以及您应该使用多少次迭代? 如果您不知道答案,那么您应该使用password_hash() ,因为密码延伸现在是密码机制的关键特性,因为CPU速度更快,并且使用GPU和FPGA以每秒数十亿次的猜测速率破解密码(使用GPU)。

    例如,您可以使用5台台式机中安装的25个GPU在6小时内破解所有8个字符的Windows密码。 这是暴力强制,即枚举和检查每个8字符的Windows密码,包括特殊字符,而不是字典攻击。 那是在2012年,截至2018年,您可以使用更少的GPU,或使用25颗GPU更快地破解。

    对于在普通CPU上运行的Windows密码也有许多彩虹表攻击,并且速度非常快。 所有这些都是因为即使在Windows 10中,Windows仍然无法使用密码或延长其密码 - 不会犯与微软一样的错误!

    也可以看看:

  • 更多关于为什么password_hash()phpass是最好的方式的最佳答案。
  • 好的博客文章给出了主要算法(包括bcrypt,scrypt和PBKDF2)的推荐“工作因素”(迭代次数)。

  • 我不会以两种不同的方式存储密码哈希值,因为那样的话系统至少和最弱的哈希算法一样弱。

    链接地址: http://www.djcxy.com/p/3665.html

    上一篇: Secure hash and salt for PHP passwords

    下一篇: Transition from thread model to actors