PHP - MD5,SHA,哈希安全性

6

我是一名使用PHP构建新网站的开发人员,我想知道最好用什么来进行哈希处理。我已经看过md5和sha1了,但有没有更安全的方法?
如果这是一个初级问题,我很抱歉,因为我刚开始学习PHP安全性,并且正在尽可能使我的网站更加安全。另外,什么是盐?
谢谢,
Waseem


1
你打算用哈希做什么?至于盐,请参见http://en.wikipedia.org/wiki/Salt_(cryptography)。 - Ed Heal
密码和用户名 - Waseem Shahwan
提示:bcrypt - 就是这样。 - Leigh
3个回答

9

首先,已经证明md5和sha1容易受到冲突攻击,并且可以被彩虹表轻松破解(当他们在他们的常见密码数据库中看到您哈希值相同时)。
目前有两种足够安全的密码方式可供使用。
第一种是sha512。 sha512是SHA2的一个子版本。 SHA2尚未被证明容易受到冲突攻击,而sha512将生成512位哈希。以下是如何使用sha512的示例:

<?php
hash('sha512',$password);

另一种选项称为 bcrypt。bcrypt 以其安全哈希而闻名。它可能是最安全且最可定制的哈希之一。
在您想开始使用 bcrypt 之前,您需要检查服务器是否已启用它。输入此代码:

<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
    echo "CRYPT_BLOWFISH is enabled!";
}else {
echo "CRYPT_BLOWFISH is not available";
}

如果返回结果显示启用了,则下一步就很容易了。要bcrypt密码,您只需要执行以下操作(请注意,为了实现更多自定义选项,请查看此如何在PHP中使用bcrypt进行哈希密码?):
crypt($password, $salt);

现在回答你的第二个问题。盐通常是一串随机字符串,当你哈希密码时添加到所有密码末尾。使用盐意味着如果有人获取了你的数据库,他们无法检查哈希后的密码是否为常见密码。检查数据库被称为使用彩虹表。哈希时应始终使用盐!!
以下是我关于SHA1和MD5碰撞攻击漏洞的证据:
http://www.schneier.com/blog/archives/2012/10/when_will_we_se.htmlhttp://eprint.iacr.org/2010/413.pdfhttp://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdfhttp://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdfUnderstanding sha-1 collision weakness

4
仅供参考:bcrypt 因其慢速而著名,而不是快速(http://codahale.com/how-to-safely-store-a-password/)。 - ckruse
@ckruse 抱歉出现错误,我会修复的 :) - C1D
bcrypt已经过时了,使用scrypt吧 ;) http://stackoverflow.com/questions/10149554/are-there-any-php-implementations-of-scrypt - Stefan Rasmusson
1
请引用您的来源,证明SHA1碰撞攻击已被证实...因为这对整个加密社区来说都是一个新闻。这里有一些参考资料 - Leigh
请完成你的作业:在这种情况下,碰撞攻击是无关紧要的;原像攻击仍然是不可行的 - Gumbo
我宁愿选择一种安全但速度较慢的方法,也不愿意使用速度快但不够安全的方法。 - Angry 84

1
盐的整个目的是为了防止攻击者将预生成哈希列表与目标哈希进行比较。
攻击者不需要为每个明文密码预先计算一个“哈希”值,而是需要为每个明文密码预先计算16384个“哈希”值(2^7 * 2^7)。
当crypt函数首次开发时,这可能会有些逊色,但现在已经不再是问题了 - 预先计算这么多密码的计算能力乘以你怀疑的明文密码数量(字典)是相当高的。
现在不再是问题,这就是为什么我们有像影子密码、除了crypt之外的其他核心密码功能以及每个系统管理员都希望您选择不会出现在字典中的密码的原因。
如果要生成的哈希值用于密码,则这是一种被广泛接受的实现方法。

http://www.openwall.com/phpass/


我不知道你是怎么得到16384这个数字的,盐值仍然非常重要。当你将每个密码与不同的盐值结合时,攻击者就必须为每个单独的密码建立一个彩虹表,不能使用一个彩虹表获取所有密码。这就是盐的目的,它不是一个秘密,也不能防止字典攻击。 - martinstoeckli
@martinstoeckli - 我认为Danilo假设盐值为两个7位ASCII字符,因此有16,384种可能性。而我认为你们“互相误解”,也就是说,我认为你们都在说同一件事情。现在不再是针对“n”个密码的彩虹表,而是针对每个“n”个密码的16K条目(或者,在概念上,现在是一个16K x“n”矩阵,而不是一个“n”元素数组)。 - Dan
@Dan - 哦,那听起来很有道理。那么我只能补充一点,今天的一个盐应该包含大约128位,例如BCrypt需要22个字符。 - martinstoeckli

0

如果您计划用于密码,那么不要使用MD5或SHA1。它们已知存在弱点和不安全性,即使加盐也是如此。

如果您将它们用于其他目的(例如提供文件哈希以确认其真实性,或者提供伪随机排序顺序的随机哈希数据库列),则它们是可以接受的(在某种程度上),但不适用于密码或任何其他需要保密的内容。

目前最佳的密码哈希算法是BCrypt,并配合适当的加盐。

在PHP中实现BCrypt密码哈希的最佳方法是使用PHP的新密码API。该API将作为内置函数集合出现在PHP的下一个版本v5.5中,预计在未来几个月内发布。好消息是,他们还发布了向后兼容版本,供当前版本的PHP(5.3和5.4)用户使用,因此即使PHP 5.5尚未发布,您也可以立即开始使用新的API。

您可以从这里下载兼容库:https://github.com/ircmaxell/password_compat

另外:您问了什么是“盐”。由于我在这个答案中提到了几次,所以我也应该解决这部分问题。

盐基本上是在哈希密码时添加的附加字符串,以使其更难破解。

例如,攻击者可能事先知道给定密码字符串的哈希值,甚至是许多给定密码字符串的哈希值。如果他能够获取您的哈希数据并且您没有使用盐,则他可以将您的哈希与已知密码列表进行比较,如果您的任何用户使用易于猜测的密码,则无论使用了什么哈希方法,他们都会在几秒钟内被破解。

但是,如果您在哈希密码时添加了一个秘密的额外字符串,那么哈希值将不匹配原始密码的标准哈希值,从而使攻击者更难找到该值。

好消息是,如果您正在使用我上面提到的API,则不需要过多担心此类细节,因为API会为您处理盐。

希望这有所帮助。


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