安全的哈希和盐用于 PHP 密码

23 浏览
0 Comments

安全的哈希和盐用于 PHP 密码

目前有人声称MD5是部分不安全的。考虑到这一点,我想知道用于密码保护的机制是哪个。

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

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

  1. 哈希机制必须在PHP中可用
  2. 它必须是安全的
  3. 它可以使用盐(在这种情况下,所有盐都一样好吗?有没有办法生成好的盐?)

此外,我应该在数据库中存储两个字段(一个使用MD5和另一个使用SHA,例如)吗?这会使它更安全还是更不安全?

如果我没有表达清楚,我想知道要使用哪些哈希函数以及如何选择好的盐以获得安全且快速的密码保护机制。

不太涵盖我的问题的相关问题:

PHP中SHA和MD5的区别是什么?

简单的密码加密

ASP.NET存储密钥、密码的安全方法

如何在Tomcat 5.5中实现盐加密的密码

admin 更改状态以发布 2023年5月22日
0
0 Comments

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

  • PHP 5.5或更高版本:password_hash()是一个质量很好的,并且是PHP核心的一部分。
  • PHP 4.x (已过时): OpenWall的phpass库比大多数自定义代码都要好得多-用于WordPress、Drupal等。

大多数程序员没有足够的专业知识,不能安全地编写与加密相关的代码而不引入漏洞。

快速自测:密码加密是什么,你应该使用多少次迭代?如果你不知道答案,那么你应该使用password_hash(),因为在现代计算机系统中,密码加密是密码机制的一个关键特征,由于CPU速度更快并且使用GPU和FPGA以每秒数十亿个猜测的速度破解密码。(使用GPU)

截至2012年,在5台台式PC中安装了25个GPU,您可以使用6小时破解所有8字符Windows密码。这是穷举,即枚举和检查每个8字符Windows密码,其中包括特殊字符,并不是字典攻击。使用现代GPU ,您当然可以破解更多密码或使用更少的GPU-或以合理的成本在云中托管GPU几个小时。

在Windows密码中,还有许多虹表攻击,这些攻击在普通CPU上运行非常快。

这一切是因为Windows仍然没有为其密码添加“盐”或“拉伸”,即使是在Windows10中也是如此。这在2021年仍然是事实。不要犯与Microsoft相同的错误!

另请参阅:

  • 优秀回答,了解更多有关password_hash()phpass是最佳选择的原因。
  • 很棒的博客文章,提供了包括bcrypt、scrypt和PBKDF2在内的主要算法的推荐“工作因素”(迭代次数)。
0
0 Comments

免责声明: 此回答是在2008年写的。

PHP自那时起,已经提供了password_hashpassword_verify,自它们引入以来,它们是推荐的密码哈希和检查方法。

然而,这份回答的理论仍然值得一读。

TL;DR

不要这么做

  • 不要限制用户可以输入密码的字符。只有白痴才这么做。
  • 不要限制密码的长度。如果用户想要使用包含supercalifragilisticexpialidocious的句子,不要阻止他们使用它。
  • 不要剥离或转义密码中的HTML和特殊字符。
  • 永远不要以纯文本方式存储用户的密码。
  • 除非他们忘记密码并且你发送了一个临时密码,否则永远不要通过电子邮件向用户发送密码。
  • 绝不要以任何方式记录密码。
  • 绝不要使用SHA1或MD5,甚至不要使用SHA256!现代破解工具可以超过每秒60亿和180亿次哈希(分别)。
  • 不要混合bcrypt和hash()的原始输出,要么使用十六进制输出,要么对其进行base64_encode。 (这适用于任何可能包含恶意\0的输入,它可以严重削弱安全性。)

应该这么做

  • 尽可能使用scrypt;如果无法使用,则使用bcrypt。
  • 如果无法使用bcrypt或scrypt,则使用带有SHA2哈希的PBKDF2。
  • 在数据库泄露时重置所有用户的密码。
  • 实施合理的8-10个字符的最小长度,加上要求至少1个大写字母,1个小写字母,一个数字和一个符号。这将提高密码的熵,从而使它更难破解。(有关一些讨论,请参见“什么样的密码好?”部分。)

为什么要哈希密码?

哈希密码的目的很简单:通过破坏数据库来防止恶意访问用户帐户。因此,密码哈希的目标是阻止黑客或破解者通过花费太多时间或金钱来计算明文密码。而时间/成本是您的最佳威慑手段。

另一个需要使用良好、健壮的哈希函数来保护用户账户的原因是为了给您足够的时间来更改系统中的所有密码。如果您的数据库受到攻击,您将需要足够的时间来至少锁定系统,如果不能更改数据库中的所有密码。

尽管最近一次密码恢复需要暴力破解他的密码保护,但Whitehat Security的CTO Jeremiah Grossman在White Hat Security博客上表示:

有趣的是,在实现这个噩梦的过程中,我了解了很多有关密码破解、存储和复杂性的知识。我开始珍视为什么密码存储的重要性远远超过了密码复杂性。如果您不知道密码是如何存储的,那么您真正能依赖的只有复杂性。这对于密码和加密专业人员来说可能是常识,但对于普通的InfoSec或Web安全专家,我非常怀疑。

(重点是我的。)

什么是一个好的密码?

。(尽管我并不完全认同Randall的观点。)

简单来说,熵是密码中的变化有多大。当一个密码只有小写罗马字母时,仅有26个字符。这并不是很大的变化。使用字母数字密码会更好,有36个字符。但是,允许使用大小写字母和符号,约有96个字符。这比仅有字母的情况要好得多。一个问题是,为了使我们的密码容易记住,我们会加入模式,这会降低熵值。哎呀!

密码熵可以很容易地进行估算。使用完整的ascii字符范围(大约96个可键入字符)可产生6.6的熵值,每个字符,8个字符的密码仍然过低(52.679位的熵值),并不适合未来的安全。但好消息是:密码越长,使用unicode字符的密码就会增加密码的熵,使密码更难被破解。

Crypto StackExchange网站上可以找到关于密码熵的更详细讨论。通过谷歌搜索也可以得到很多结果。

在评论中,我与@popnoodles交流,他指出强制执行密码策略,如X长度的密码,需要X个字母,数字,符号等,实际上可以通过使密码方案更可预测来降低熵。我同意。尽可能地随机,真正随机是最安全但记忆最差的解决方案。

到目前为止,我能够发现,制作世界上最好的密码是一个进退两难的问题。它要么不够记忆,要么太容易预测,要么太短,要么有太多的Unicode字符(难以在Windows/Mobile设备上输入),要么太长等等。没有一种密码是真正足够好的,因此我们必须像保护肯塔基州的Fort Knox一样保护它们。

最佳实践

bcrypt和scrypt是当前最佳实践。在未来,Scrypt将比bcrypt更好,但它还没有被Linux/Unix或web服务器采用为标准,并且还没有对其算法进行深入的审查。但仍然,该算法的未来看起来很有前途。如果你在使用Ruby,有一个scrypt gem可以帮助你,现在Node.js有自己的scrypt包。你可以通过Scrypt扩展或Libsodium 扩展(两者都可在PECL中获取)在PHP中使用Scrypt。

如果你想了解如何使用bcrypt,我强烈建议阅读 crypt函数的文档,或者找到一个好的封装器,或者使用PHPASS进行更加传统的实现。我建议最少使用12轮的bcrypt,如果不是15到18轮。

当我了解到bcrypt只使用blowfish的密钥调度和可变的成本机制时,我改变了对使用bcrypt的想法。后者可以通过增加已经昂贵的blowfish密钥调度来增加暴力破解密码的成本。

一般实践

我几乎无法想象这种情况。PHPASS支持PHP 3.0.18到5.3,因此它可以在几乎所有想象得到的安装上使用,如果您不确定您的环境是否支持bcrypt,建议使用PHPASS。

但是假设您完全无法使用bcrypt或PHPASS,那么怎么办呢?

尝试使用PDKBF2的实现,使用环境/应用程序/用户感知可以容忍的最大轮数。我建议的最低轮数是2500轮。此外,如果可用,请使用hash_hmac()使操作更加难以复制。

未来的实践

PHP 5.5中带来了一个完整的密码保护库,它抽象了工作中任何使用bcrypt的痛苦。虽然我们大多数人在常见的环境中(尤其是共享主机)只能使用PHP 5.2和5.3,但@ircmaxell为即将到来的API构建了一个兼容层,向后兼容PHP 5.3.7。

密码学回顾和免责声明

实际破解散列密码所需的计算能力并不存在。计算机“破解”密码的唯一方法是重新创建它并模拟用于保护它的散列算法。哈希速度与其能够被暴力破解的能力线性相关。更糟糕的是,大多数哈希算法可以轻松并行化以更快地执行。这就是为什么如bcrypt和scrypt这样的代价高昂的方案如此重要。

你无法预见所有的威胁或攻击途径,所以你必须尽力保护你的用户起初。如果你不这样做,那么你可能甚至没有意识到自己已受到攻击,直到太晚了......而且你是有责任的。为了避免这种情况,一开始就要表现得多疑心。攻击你自己的软件(内部),尝试窃取用户凭据,或修改其他用户的帐户或访问其数据。如果你没有测试你的系统的安全性,那么除了你自己,你不能责怪任何人。

最后:我不是密码专家。我说的话都是我的观点,但我认为它们基于纯粹的常识......以及大量的阅读。记住,要尽可能地多疑,使事情尽可能难以侵入,然后,如果你仍然担心,联系一个白帽黑客或密码学家,看看他们对你的代码/系统说什么。

0