PHP密码的安全哈希和盐值

1249

目前有人称MD5算法存在部分不安全的问题。考虑到这一点,我想知道哪种机制适合用于密码保护。

一个名为《双重哈希是否比单次哈希更不安全?》的问题建议多次哈希可能是个好主意,而《如何为单个文件实现密码保护?》则建议使用盐。

我使用PHP。我想要一个既安全又快速的密码加密系统。虽然密码哈希百万次可能更安全,但也更慢。如何在速度和安全之间取得平衡?此外,我希望结果具有恒定数量的字符。

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

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

如果我的表述不够清晰,我想知道哪些哈希函数和如何选择好的盐以获得一个既安全又快速的密码保护机制。

以下是一些相关问题,但并未完全涵盖我的问题:

SHA和MD5在PHP中有什么区别
简单密码加密
ASP.NET安全存储密钥、密码的方法
如何在Tomcat 5.5中实现加盐密码


14
http://www.openwall.com/phpass/ 是一个非常不错的库。 - Alfred
60
MD5现在已完全不安全。 - JqueryToAddNumbers
3
这取决于您使用它的目的。对于彩虹表匹配或简单暴力破解未加盐的MD5密码来说很容易,但是如果使用良好的盐值,构建用于快速破解密码集的彩虹表仍然极其不切实际,并且暴力破解也不可行。 - Craig Ringer
14
PHP 5.5+内置了安全的密码哈希函数。http://php.net/manual/en/function.password-hash.php - Terence Johnson
如何使用PHP 5.5密码哈希函数 - Sliq
显示剩余4条评论
14个回答

1030
免责声明:本答案是在2008年编写的。
自那时以来,PHP给我们提供了password_hashpassword_verify,自从它们被引入以来,它们是推荐的密码哈希和检查方法。
尽管如此,这个答案的理论仍然值得一读。

简短概述

不要做的事情

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

Do's

  • 如果可以,请使用scrypt;如果不能,请使用bcrypt。
  • 如果无法使用bcrypt或scrypt,请使用带有SHA2哈希的PBKDF2。
  • 当数据库被攻击时,请重置所有用户密码。
  • 实现合理的8-10个字符最小长度,同时要求至少1个大写字母、1个小写字母、一个数字和一个符号。这将提高密码的熵,从而使其更难破解。(请参见“什么是好密码?”部分进行一些辩论。)

为什么要哈希密码?

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

另一个你想要在用户帐户上有一个好的、强大的哈希的原因是给你足够的时间来改变系统中的所有密码。如果您的数据库被攻击,您需要足够的时间来至少锁定系统,如果可能,更换数据库中的每个密码。

Jeremiah Grossman,Whitehat Security的CTO,在最近一次需要强制破解他的密码保护的密码恢复之后在White Hat Security博客上说

有趣的是,在经历这个噩梦时,我学到了很多关于密码破解、存储和复杂性的知识。我开始认识到为什么密码存储比密码复杂性更重要。如果你不知道你的密码是如何存储的,那么你所依赖的只是复杂性。对于密码和加密专家来说,这可能是常识,但对于普通信息安全或网络安全专家来说,我非常怀疑。
(强调是我的。)
好的密码应该具有。 (虽然我并不完全认同Randall的观点。)
简而言之,熵是密码中包含多少变化。当一个密码只有小写罗马字母时,只有26个字符。这并不是很多变化。字母数字密码更好,有36个字符。但允许使用大写和小写字母以及符号,大约有96个字符。这比仅使用字母要好得多。问题之一是,为了使密码易记,我们会插入模式,从而降低熵。哎呀!
密码熵可以轻松近似计算。使用ascii字符的全部范围(大约96个可输入字符)可产生每个字符6.6的熵,对于8个字符的密码来说仍然太低(52.679比特的熵)以保证未来的安全性。但好消息是:更长的密码和带有Unicode字符的密码确实增加了密码的熵,使其更难破解。

Crypto StackExchange网站上有关于密码熵的更长讨论。良好的Google搜索也会得到很多结果。

在评论中,我与@popnoodles交谈,他指出强制使用X个字母、数字、符号等长度为X的密码策略实际上会通过使密码方案更加可预测来降低熵。我同意。随机性越真实的解决方案总是最安全但记忆最差的解决方案。

就我所知,创造世界上最好的密码是一个进退两难的局面。它要么不容易记忆,太容易预测,太短,太多Unicode字符(在Windows/Mobile设备上难以输入),太长等等。没有任何一个密码对我们的目的来说是完全足够的,因此我们必须像保护金库一样保护它们。

最佳实践

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

我建议阅读crypt函数的文档以了解如何使用bcrypt,或者找到一个好的 包装器或使用类似于PHPASS的更传统的实现。如果不是15至18轮,则建议至少使用12轮bcrypt。
当我了解到bcrypt仅使用blowfish的密钥计划和可变成本机制时,我改变了对使用bcrypt的想法。后者使您可以通过增加blowfish已经昂贵的密钥计划来增加暴力破解密码的成本。

平均实践

我几乎无法再想象这种情况了。PHPASS支持PHP 3.0.18到5.3,因此几乎可以在任何可想象的安装上使用 - 如果您不确定您的环境是否支持bcrypt,应该使用它。
但是假设您根本无法使用bcrypt或PHPASS。那么怎么办?
尝试使用PDKBF2的实现,其最大轮数应该与您的环境/应用程序/用户感知能够承受的范围相符。我建议的最低轮数是2500轮。此外,请确保使用hash_hmac()(如果可用)使操作更难以复制。

未来实践

PHP 5.5中即将推出一个全面的密码保护库,它抽象了使用bcrypt时的任何痛苦。虽然我们大多数人在常见环境中仍然使用PHP 5.2和5.3,特别是共享主机,但@ircmaxell已经为即将推出的API构建了一个兼容层,向后兼容到PHP 5.3.7。

密码学回顾和免责声明

计算机需要的计算能力来实际“破解”一个散列密码是不存在的。计算机“破解”密码的唯一方法就是重新创建它并模拟用于保护它的哈希算法。哈希速度与其被暴力破解的能力成线性关系。更糟糕的是,大多数哈希算法都可以轻松并行化以加快速度。这就是为什么像bcrypt和scrypt这样昂贵的方案如此重要。
你不可能预见所有的威胁或攻击途径,因此你必须尽最大努力保护你的用户。如果你不这样做,甚至可能错过你被攻击的事实,直到为时已晚......而你会有责任。为了避免这种情况,从一开始就要表现得多疑。攻击你自己的软件(内部)并尝试窃取用户凭据,或修改其他用户的帐户或访问其数据。如果你不测试系统的安全性,那么你只能责怪自己。
最后:我不是密码学家。我说的任何话都是我的观点,但我碰巧认为这是基于老套的常识...和大量的阅读。记住,尽可能地多疑,让事情尽可能难以侵入,然后,如果你仍然担心,联系一个白帽黑客或密码学家看看他们对你的代码/系统有何建议。

10
如果攻击者能够获取您的密码数据库,那么秘密就无法保护了,因为密码数据库本来就应该是保密的。但很重要的一点是盐值必须是随机的,这点需要特别注意。 - frankodwyer
6
@wicked flea,我不是在和你争论。只是指出我们工作中这个领域的复杂和繁琐之处。我一直希望能够从那些全能、最聪明、最好的实践中获得关于如何设置小型网站内容管理系统的指导。我还在学习中。...每当我读到有道理的东西时,很快就会注意到其他5篇文章的观点与之相矛盾。这种来回反复很快就会令人头晕 :) - OldBuildingAndLoan
4
有趣的修改。用户ID(比如自增的BIGINT)是一个好的nonce吗?或者因为它不是随机的,所以它不好?另外,我将不得不在数据库中为每个用户存储nonce... 站点密钥+nonce+HMAC是否提供了比多次迭代的带有用户ID盐的哈希更显著的安全性提升?同样地,多次迭代HMAC对于安全性来说是好的吗? - luiscubal
4
通过电子邮件发送一个需要用户在第一次使用时更改的临时密码,以及发送一个“安全”的链接让用户设置他们的密码是同样有风险的。无论哪种情况,只要拦截了该邮件,任何人在预期收件人使用链接或密码之前都可以访问该帐户。 - Tim Gautier
3
通过扩展字符集,密码的组合数会增加。但是通过强制所有密码遵循规则,则可能选项减少了。假设有人试图用暴力破解获得密码。通过告诉他们用户的密码必须具备1个大写字母、1个小写字母、1个数字和1个符号,这意味着他们需要尝试的次数显著减少。通过允许用户自己决定密码组合,黑客就需要更加努力地尝试。 - Popnoodles
显示剩余44条评论

145
一个更简单和更安全的解决方案是 - 根本不要自己编写密码机制,而是使用经过验证和测试的机制:
对于 PHP 8(2023年的当前版本),使用password_hash() - 这是一个质量很好的机制,自 PHP 5.5 起就是 PHP 核心的一部分。
大多数程序员在不引入漏洞的情况下,都没有编写与加密相关的代码的专业知识。

快速自测

如果你不知道密码拉伸是什么以及应该使用多少次迭代,那么你应该使用password_hash(),因为由于更快的 CPU 和GPU 和 FPGA用于以每秒数十亿次猜测(使用 GPU)的速度破解密码,密码拉伸现在是密码机制的一个关键特性。

示例:破解 Windows 密码

截至2023年,你可以使用8个GPU在48分钟内破解所有8位字符的Windows密码(使用hashcat,NTLM密码的每秒2880亿个哈希值)。
这是一种暴力破解,即枚举和检查每个8位字符的Windows密码,包括特殊字符,而不是字典攻击。
2023年的例子比2012年快了大约7.5倍,当时你可以使用25个GPU在6小时内破解所有8位字符的Windows密码
现在你还可以以合理的价格在云端租用GPU几个小时。

为什么Windows密码很容易被破解?

这一切都是因为Windows仍然没有对其密码进行加盐或拉伸,即使在Windows 10或11中也是如此,因为它需要允许NTLMv1登录。

这在2023年仍然是事实 - 请参阅此问答。

不要犯和微软一样的错误!

另请参阅

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

传统PHP

对于非常旧的PHP(4.x):OpenWall的phpass库比大多数自定义代码更好 - 在WordPress、Drupal等中使用。


3
但这些系统更为人所知,可能已经受到了攻击。但是,如果你不知道该怎么做,使用这些系统要比自己制作更好。 - JqueryToAddNumbers
16
“这些系统更为人所知,可能已经受到攻击” - 仅仅因为一个良好设计的认证系统更为人们熟知并不意味着它已经被攻击了。像phpass这样的库是由专家编写并经过许多人详细审查的 - 它们广为人知的事实伴随着不同人员的详细审查,更有可能意味着它们是安全的。 - RichVel
2
“根本不要编写自己的密码机制” - 但真正的偏执者会想要编写自己的密码机制,以最小化NSA留下后门的可能性。 - PP.
3
在我看来,经过同行评审的密码哈希算法存在NSA后门的可能性非常低。而不是真正的加密专家编写新的密码哈希机制而没有其他漏洞的可能性更低。而典型的Web应用程序仅使用MD5或SHA-1哈希,这很糟糕 - 即使是Chris Shiflett的优秀著作《Essential PHP Security》也推荐使用MD5... - RichVel
1
@RichVel - password_hash() 函数。正如之前提到的,它是内置于 PHP 核心(也称为 /ext/standard)中的。 - CubicleSoft
显示剩余4条评论

46

我不会以两种不同的方式存储哈希密码,因为这样系统的弱点至少和使用的哈希算法中最弱的一种一样。


45

从PHP 5.5开始,PHP具有用于哈希和验证密码的简单且安全的函数:password_hash()password_verify()

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false
当使用password_hash()函数时,它会生成一个随机盐并将其与算法和密码成本一起包含在输出的哈希中。然后,password_verify()函数读取该哈希值并确定所使用的盐和加密方法,并将其与提供的纯文本密码进行验证。
提供PASSWORD_DEFAULT指令告诉PHP使用已安装的PHP版本的默认哈希算法。未来的版本中,这意味着确切使用哪个算法可能会发生变化,以便始终使用其中一个最强大的可用算法。
增加成本(默认为10)会使哈希更难以被暴力破解,但也意味着生成哈希和校验密码所需的服务器CPU工作量更大。
请注意,即使默认哈希算法可能会更改,旧的哈希仍将继续正确验证,因为所使用的算法存储在哈希中,password_verify()会检测到它。

33

虽然这个问题已经得到了回答,但我想再强调一下,用于哈希的盐应该是随机的,而不像第一个答案中建议的那样使用电子邮件地址。

更多解释请参见(archive.org的备份)http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

最近我进行了一次讨论,讨论的问题是用随机位盐串联密码哈希是否比使用可猜测或已知盐更加安全。以下是我的看法:

如果存储密码的系统以及存储随机盐的系统都被攻击者入侵,攻击者将能够访问哈希和盐,因此无论盐是否随机并不重要。攻击者可以生成预计算的彩虹表来破解哈希。现在有趣的部分来了-生成预计算表不是一件轻松的事情。我们以WPA安全模型为例。你的WPA密码实际上从未发送到无线接入点。相反,它会与你的SSID(网络名称-例如Linksys、Dlink等)一起哈希。这里有一个非常好的解释。要从哈希中检索密码,您需要知道密码以及盐(网络名称)。Church of Wifi已经预先计算了具有前1000个SSID和约1百万个密码的哈希表。所有表的大小约为40 GB。正如您可以在他们的网站上读到的那样,有人用15个FGPA数组花了3天时间来生成这些表。

假设受害者使用SSID“a387csf3”和密码“123456”,这些表能否破解它?不行!..不能。即使密码很弱,也没有SSID a387csf3的哈希。这就是使用随机盐的优点所在。它会阻止那些依赖于预计算表的黑客入侵。是否能够阻止决心很强的黑客?可能不行。但使用随机盐确实提供了额外的防御层。

谈到这个话题,让我们探讨将随机盐值存储在独立系统上的额外优势。

场景1:密码哈希值存储在系统X上,用于哈希的盐值存储在系统Y上。这些盐值是可以猜测或已知的(例如用户名)。

场景2:密码哈希值存储在系统X上,用于哈希的盐值存储在系统Y上。这些盐值是随机的。

如果系统X被攻击者攻破,显然使用独立系统上的随机盐值(场景2)有很大优势。攻击者需要猜测附加值才能破解哈希值。如果使用32位盐值,则每个猜测的密码可能需要4,294,967,296(约42亿)次迭代。


7
即使攻击者获取了盐值,由“站点盐值:用户盐值:密码”组成的字符串仍然具有对抗预计算表的特性,因为攻击者需要为每个用户生成表(因此攻击变得更慢),除非当然是针对特定用户进行攻击... - luiscubal
关于“即使攻击者获得了盐值,'sitesalt:usersalt:password' 字符串仍然抵御预先计算的表格”这一点,我完全同意。我的观点是如果 sitesalt 是随机和较长的,则会比 sitesalt 可预测更加安全。我看到有些人建议使用电子邮件 ID 等作为盐值,我不赞成这种做法。 - Gaurav Kumar
你忽略了我最开始写的内容。我说要使用一个随机nonce,与记录一起存储,再加上电子邮件地址。添加电子邮件地址可以为黑客提供额外的熵值。我后来改写了我的答案,支持使用bcrypt。 - Robert K

29

我想指出的是,PHP 5.5包含一个密码哈希API,它提供了一个对crypt() 的包装器。该API显着简化了哈希、验证和重新哈希密码哈希的任务。作者还发布了一个兼容性包(以单个password.php文件的形式提供,只需require即可使用),供那些使用PHP 5.3.7及更高版本并希望立即使用此功能的人使用。

目前仅支持BCRYPT,但旨在轻松扩展以包括其他密码哈希技术,并且因为技术和成本存储为哈希的一部分,所以对您首选的哈希技术/成本的更改不会使当前哈希无效,框架将自动使用正确的技术/成本进行验证。如果没有明确定义自己的,则还处理生成“安全”盐。

该API公开了四个函数:

  • password_get_info() - 返回给定哈希的信息
  • password_hash() - 创建密码哈希值
  • password_needs_rehash() - 检查给定哈希值是否与给定选项匹配。有助于检查哈希值是否符合您当前的技术/成本方案,以便在必要时重新哈希
  • password_verify() - 验证密码是否与哈希值匹配

目前这些函数接受PASSWORD_BCRYPT和PASSWORD_DEFAULT密码常量,它们目前是同义词,不同之处在于PASSWORD_DEFAULT“可能会在新的PHP版本中支持更强的哈希算法时更改”。在登录时使用PASSWORD_DEFAULT和password_needs_rehash()(如果需要,重新哈希)应该可以确保您的哈希在很小或没有工作的情况下相对耐用,抵御暴力攻击。

编辑:我刚意识到Robert K的答案中已经简要提到了这一点。我将保留此答案,因为我认为它提供了更多关于如何工作以及为那些不知道安全性的人提供易用性的信息。


21

我正在使用Phpass,这是一个简单的单文件PHP类,几乎可以在每个PHP项目中轻松实现。还请参阅The H

默认情况下,它使用Phpass中实现的最强加密bcrypt,并回退到其他加密方式(如MD5)以提供向后兼容性,以适应像WordPress这样的框架。

返回的散列值可以按原样存储在数据库中。生成散列的示例用法如下:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

为了验证密码,可以使用以下方法:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

15

记住的事情

关于 PHP 的密码加密,已经有很多讲解了,其中大部分都是非常好的建议,但在你开始使用 PHP 进行密码加密之前,请确保你已经实施或准备好以下内容。

服务器

端口

无论你的加密有多好,如果你没有正确保护运行 PHP 和 DB 的服务器,那么所有的努力都是毫无意义的。大多数服务器的功能都是相对相同的,它们都有指定的端口,允许你通过 ftp 或 shell 远程访问。确保你更改默认端口,不管你正在使用哪种远程连接方式。如果你不这样做,实际上就使攻击者少进行了一步,即进入你的系统。

用户名

为了世界的和平,请不要使用 admin、root 或类似的用户名。此外,如果你使用的是基于 unix 的系统,不要让 root 账户登录可见,它应该只限于 sudo 。

密码

你要求你的用户制作好的密码以避免被黑客攻击,自己也要这样做。如果你的后门大开着,那么锁好前门还有什么意义呢?

数据库

服务器

理想情况下,你希望 DB 和 APPLICATION 在分别的服务器上。由于成本原因,这并不总是可能的,但它确实可以提供一些保护措施,因为攻击者将需要经过两个步骤才能完全访问系统。

用户

始终为你的应用程序准备一个专用的帐户来访问 DB,并仅赋予必要的权限。

然后为自己准备一个单独的用户帐户,该帐户不会存储在服务器上的任何地方,甚至不会存储在应用程序中。

像以往一样,请不要使用 root 或类似的用户名。

密码

遵循所有好密码的相同准则。此外,不要在相同系统上的任何服务器或 DB 帐户上重复使用相同的密码。

PHP

密码

永远不要将密码存储在数据库中,而是存储其哈希值和唯一盐值,稍后我会解释为什么这样做。

哈希

单向哈希!!!!!永远不要以可逆的方式对密码进行哈希,哈希应该是单向的,这意味着您不会将其反转并将其与密码进行比较,而是以相同的方式对输入的密码进行哈希并比较两个哈希值。这意味着即使攻击者可以访问数据库,他也不知道实际密码是什么,只知道其结果哈希值。这意味着在最坏的情况下为您的用户提供更多的安全保障。

有很多好的哈希函数(password_hashhash等),但您需要选择一个好的算法才能使哈希值有效。(bcrypt和类似于它的算法都比较不错。)

当哈希速度至关重要时,速度越慢,就越抵抗暴力攻击。

哈希中最常见的错误之一是哈希值对于用户来说不是唯一的。这主要是因为盐值没有被唯一生成。

加盐

在对密码进行哈希之前,密码应始终被加盐。加盐将一个随机字符串添加到密码中,使得相似的密码在数据库中不会出现相同的情况。然而,如果盐没有为每个用户唯一生成(即:您使用硬编码盐),那么您就基本上使盐失去了价值。因为一旦攻击者找出一个密码的盐,他就有了所有密码的盐。

当您创建盐时,请确保它对于它正在加盐的密码是唯一的,然后将完成的哈希和盐存储在您的数据库中。这将使攻击者必须逐个破解每个盐和哈希才能获得访问权限。这对攻击者来说意味着更多的工作和时间。

用户创建密码

如果用户通过前端创建密码,那么就意味着密码必须发送到服务器。这会导致安全问题,因为这意味着未加密的密码正在被发送到服务器,如果攻击者能够监听和访问它,那么 PHP 中所有的安全都将毫无价值。一定要安全地传输数据,可以通过 SSL 完成,但是请注意,即使 SSL 也不是完美的(OpenSSL 的 Heartbleed 缺陷就是一个例子)。

此外,请确保用户创建一个安全密码,这很简单,也应该经常做,最终用户会感激的。

最后,无论您采取什么安全措施,没有什么是100%安全的,保护技术越先进,攻击越变得先进。但是遵循这些步骤将使您的网站更安全,攻击者的兴趣将大大降低。

这是一个 PHP 类,可以轻松创建密码的哈希和盐

http://git.io/mSJqpw


1
你应该从你的可靠哈希算法列表中删除SHA512,因为它太快了。只有在与PBKDF2结合使用时才使用它。虽然BCrypt基于Blowfish,但Blowfish本身是一种加密算法,而不是哈希算法。 - martinstoeckli
1
你如何将随机盐存储在数据库中?我认为你不会对其进行哈希处理(不能用于验证),也不会明文存储(如果攻击者能够读取数据库,则没有实际好处)。那么,你是如何做到的呢? - Iazel
wmfrancia写道:“加盐会向密码添加一个随机字符串,因此在DB中不会出现相似的密码”。这对我来说没有意义。在DB中的哈希值已经是不同的,因为这是哈希函数的属性。 - H2ONaCl
wmfancia提到了一个常量盐值的问题:“一旦攻击者找出了一个密码盐值,他就拥有了所有密码的盐值”。同样的道理也适用于如果黑客找出了哪个数据库字段是盐值,他就可以得到所有密码的盐值。由于常量盐值可能不会存储在数据库中,这是关于常量盐值的一个好处。 - H2ONaCl
当然,这些评论并不是要表明每个用户一个随机盐比每个应用程序一个盐更好。它确实更好。 - H2ONaCl

12

谷歌表示SHA256已经可用于PHP。

您绝对应该使用盐。我建议使用随机字节(而不是仅限于字符和数字)。通常情况下,您选择的字节越长,它就越安全,但速度也会变慢。我猜64个字节应该足够了。


13
64位应该对任何人来说都足够了? - Konerak
@Konerak,20年后我还会回来看看这个。 :) 但是是的,SHA256确实可用。如果你想知道SHA256有多安全,你可能需要查看这个链接:http://security.stackexchange.com/questions/90064/how-secure-are-sha256-salt-hashes-for-password-storage - Vincent Edward Gedaria Binua

8

从数学上讲,双哈希并没有提供任何好处。然而,在实践中,它对于防止基于彩虹表的攻击非常有用。换句话说,它与使用盐值进行哈希处理的效果相同,但在应用程序或服务器上需要更少的处理器时间。


2
多重哈希也能防止字典攻击和暴力破解攻击——即使攻击者使用这些方法,也只会让计算时间变长。 - frankodwyer
6
双重哈希不会为您带来显著优势,但多轮哈希迭代仍然是防御字典和暴力攻击的可行方法。工业级密码哈希使用1000+轮。PKCS#5的PBKDF1建议最少使用1000轮。 - Berk D. Demir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接