SHA1 vs md5 vs SHA256:哪个用于PHP登录?


133

我正在进行php登录,并且试图确定是使用SHA1还是Md5,还是我在另一stackoverflow文章中了解到的SHA256。他们中的任何一个比其他人更安全吗?对于SHA1 / 256,我还使用盐吗?

另外,这是将密码作为哈希存储在mysql中的安全方法吗?

function createSalt()
{
    $string = md5(uniqid(rand(), true));
    return substr($string, 0, 3);
}

$salt = createSalt();

$hash = sha1($salt . $hash);


另请参阅此答案,并阅读有关密码哈希的部分。
杰克

Answers:


110

都不行 您应该使用bcrypt。您提到的哈希都经过优化,可以在硬件上快速便捷地使用,因此破解它们具有相同的质量。如果您别无选择,请至少确保使用长盐并重新哈希多次。

在PHP 5.5+中使用bcrypt

PHP 5.5提供了用于密码哈希的新功能。这是在现代Web应用程序中存储密码的推荐方法。

// Creating a hash
$hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
// If you omit the ['cost' => 12] part, it will default to 10

// Verifying the password against the stored hash  
if (password_verify($password, $hash)) {
    // Success! Log the user in here.
}

如果您使用的是旧版本的PHP ,则确实应该升级,但在这样做之前,您可以使用password_compat公开此API。

另外,请让我们password_hash()为您生成盐。它使用CSPRNG

bcrypt的两个警告

  1. Bcrypt会自动截断任何长度超过72个字符的密码。
  2. Bcrypt将在任何NUL字符后截断。

(这里有两个警告的概念证明。)

您可能会想通过先散列密码来解决第一个警告,然后再通过bcrypt运行它们,但这会导致您的应用程序先运行到后一个。

不用编写自己的方案,而使用由安全专家编写和/或评估的现有库。

TL; DR - 使用bcrypt


1
另外,我对此很陌生:sha1,sha256和md5是否都是您所指的“哈希”?
托尼·史塔克

3
是。我指的是SHA1,SHA256和MD5以及其他针对速度进行了优化的其他哈希。您不想使用针对速度进行了优化的哈希来保护密码。有很多很好的文章讨论为什么,我这样一个特别: chargen.matasano.com/chargen/2007/9/7/...
约翰内斯Gorset

4
自PHP 5.3起,它就包含在“ crypt”函数中。如果您有较早的版本,我将考虑使用“ phpass”框架来获得下一个优点。
Johannes Gorset'2

3
@Stanislav Palatnik SHA512是一个很好的选择。不要误会我的意思;我并不是说经过扩展和加盐的SHA512哈希是不安全的。是安全的。即使这样,事实仍然是bcrypt 安全,因此我认为没有理由不使用它。
Johannes Gorset'2

10
@Cypher:bcrypt设计为缓慢,以便同样缓慢地破解。
Johannes Gorset

23

我认为使用md5或sha256或针对速度进行了优化的任何哈希值都很好,并且很好奇听到其他用户可能会遇到的麻烦。这是我的原因

  1. 如果允许用户使用弱口令如神,爱情,战争,和平那么无论你仍然会允许用户键入密码的哈希和这些密码往往先使用加密功能,因此这是打算与加密有关。

  2. 如果您未使用SSL或没有证书,则侦听流量的攻击者将能够提取密码,并且使用javascript等进行加密的任何尝试都是客户端方法,很容易被破解和克服。再次,这是打算有任何瓜葛与服务器端的数据加密。

  3. 蛮力攻击将利用弱口令,并再次因为你允许用户输入数据,如果你不具备的3登录限制,甚至更多一点,那么问题将再次具有任何与数据加密。

  4. 如果您的数据库遭到破坏,那么无论您进行何种加密,都很可能已经破坏了一切,包括哈希技术。同样,这可能是员工不满的XSS攻击或sql注入,或其他与您的密码加密无关的攻击。

我确实相信您仍然应该加密,但我能看到的唯一加密内容是防止已经拥有或以某种方式获得数据库访问权限的人只是大声读出密码。如果是未经授权的数据库访问者,那么您有更大的问题要担心,这就是Sony为何要使用它,因为他们认为加密密码可以保护包括信用卡号在内的所有内容,因此只能保护一个字段。

对于数据库中的密码进行复杂的加密,我唯一能看到的唯一好处就是延迟了可以访问数据库的员工或其他人员仅读取密码。因此,如果这是一个小项目或其他事情,我将不必担心服务器端的安全性,而应该担心有关保护客户端可能发送到服务器的任何内容(例如sql注入,XSS攻击或多种其他方式)的担心。可能会受到损害。如果有人不同意,我希望从客户端读取一种必须使用超级加密密码的方式。

我想尝试阐明这一点的原因是,人们常常认为加密密码意味着他们不必担心密码被泄露,而不必担心网站的安全性。


1
说得好。网络安全将比哈希技术更受青睐,因为哈希技术不仅可以保存您的数据,而且还可以使服务器防御做好准备。
2013年

14
这真的是误会。当然,安全地对数据库中的密码进行哈希处理并不能提高应用程序级别或数据库级别的安全性。安全性不是全部。您要出于两个原因安全地对数据库中的用户密码进行哈希处理;首先,客户信任他们的密码,他们可能会或可能不会在其他站点上使用该密码,因此,即使您的数据库受到损害,您也要确保此密码不可恢复;其次,为了安全起见,您希望免除责任违反。我不知道会有任何官司,但是泄露密码会使您的公司看上去非常糟糕。
詹姆斯·麦克马洪

6
这是个坏建议。如果有人窃取了您的数据库并获得了您所有的哈希密码,即使他们也破坏了数据库的其他部分,那么防止他们破解密码并登录仍然很重要。(例如,想想一个银行网站。)速度优化算法使攻击者能够针对被盗的哈希测试许多候选对象,直到找到匹配为止。即使使用bcrypt和scrypt之类的算法知道您使用的是哪种算法,也使测试候选者进行哈希运算变得缓慢且昂贵。因此,如果有人窃取了哈希,它们将提供更好的保护。
理查德

6
“如果您的数据库遭到破坏,那么无论您做得多么神秘,很可能一切都受到了破坏,包括哈希技术。” 这就是为什么 bcrypt如此重要的原因。使用bcrypt,某人是否具有哈希值并不重要。使用像SHA1 / MD5这样的快速哈希算法,它可以做到。
ceejayoz 2015年

我认为,有些人所缺少的一点是,当所有其他数据都是明文时,密码是否为1000%安全无关紧要。例如,如果整个数据库遭到破坏,则黑客现在拥有所有明文信用卡号。是的,许多人在不同的网站上使用相同的密码,但是已经被告知他们不做此事,所以这不再是我们的问题。如果数据库本身包含敏感信息,并且涉及到它的危害,那么请按照您认为必要的强度对整个数据库进行加密。
UncaAlby

15

正如Johannes Gorset指出的那样,Matasano Security的Thomas Ptacek的帖子解释了为什么简单的通用哈希函数(例如MD5,SHA1,SHA256和SHA512)是较差的密码哈希选择

为什么?它们太快了-您可以使用现代计算机计算出每个内核至少每秒1,000,000个MD5哈希,因此针对人们使用的大多数密码都是可行的。而且,这比基于GPU的破解服务器集群要少得多!

没有键拉伸的盐析仅意味着您无法预先计算彩虹表,您需要为特定的盐临时构建它。但这并不会使事情变得那么困难。

用户@Will说:

每个人都在谈论这个问题,就像他们可以通过互联网被黑客入侵一样。如前所述,限制尝试使得不可能通过Internet破解密码,并且与哈希无关。

他们不需要。显然,对于LinkedIn,他们使用了常见的SQL注入漏洞来获取登录数据库表并离线破解了数百万个密码。

然后,他回到离线攻击场景:

当整个数据库遭到破坏时,安全性才真正发挥作用,然后黑客可以每秒针对md5哈希执行1亿次密码尝试。SHA512慢大约10,000倍。

不,SHA512并不比MD5慢10000倍-仅需大约两倍。另一方面,Crypt / SHA512是一种非常不同的野兽,与BCrypt / SHA512一样,它执行密钥拉伸,并使用内置的随机盐生成完全不同的哈希,计算所需的时间在500到999999倍之间(拉伸是可调的)。

SHA512 => aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
Crypt/SHA512 => $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

因此,PHP的选择是Crypt / Blowfish(BCrypt),Crypt / SHA256或Crypt / SHA512。或至少是Crypt / MD5(PHK)。参见www.php.net/manual/en/function.crypt.php


简单的密码哈希是可以的,它取决于防火墙以确保服务器安全..“防火墙”是指一种反应性防火墙,可以阻止/减慢暴力破解(人类只能快速键入THAT)。竞赛是没有意义的...“如果某个黑客闯入了,现在拥有了一切,那该怎么办”(面对面)-如果一个黑客进入了您的服务器,那就结束了。密码被破解主要是因为它们太简单了,或者软件开发者太懒了以至于无法像网络犯罪分子那样思考。

@argon请重读。散列密码的全部目的是为了让您登录数据库被泄露(它会在某个时候),你不要马上泄露所有用户的密码,这是最经常被用户在不同重用的网站,否则简单输入后会有延迟。而“如果他们进入您的服务器,游戏就结束了”是有争议的,因为他们不需要进入您的服务器。黑客最常使用的漏洞是SQL注入(请参见Linkedin案例),然后他们对哈希进行暴力破解。这就是为什么需要加盐和拉伸。
LexLythius

如果对安全性的要求确实很高,那么将密码存储在其他位置可能是个好主意。有多种方法可以保护您的数据(和源代码)-对于“如果/何时” ..-但是将密码哈希化为“十亿比特”的安全性只有这样:密码创建者/来宾系统,数据传输以及服务于服务器硬件的人员。话虽这么说:我并不是说哈希是没有用的,但是我说的是,如果您的解决方案只是更复杂的哈希,那么恐怕在不久的将来,量子计算机将无法使用。

递归散列会增加任何黑客尝试的工作量/成本。迭代次数越多,破解越难,因此甚至可以使用SHA256之类的快速哈希。迭代必须是随机的,并且可以公开。password_hash()在散列本身中显示成本。
维克多·斯托达德

@VictorStoddard是的,您可以滚动自己的哈希方案并提供可调整的密钥扩展。但是,为什么你会这样做,而不是使用现有的,更彻底地审查算法,专家们已经创建并出于这样的目的提供?
LexLythius

13

使用SHA256。它不是完美的,就像SHA512快速散列的理想选择一样,但是在所有选项中,它是绝对的选择。根据任何哈希技术,请确保对哈希加盐以增加安全性。

作为补充,FRKT,请告诉我哪里有人可以轻松破解咸化的SHA256哈希?看到这一点我真的很感兴趣。

重要编辑:

继续前进,请bcrypt用作强化的哈希。可以在此处找到更多信息。


编辑盐腌:

使用随机数或随机字节流等。您也可以将数据库中记录的唯一字段用作盐,这样,盐对每个用户而言都是不同的。


1
但是它们针对速度进行了优化,这意味着它们可以启用暴力破解。
arbales 2010年

6
事实仍然存在,这是为了保护密码。通过使用带有盐的哈希值,然后在网站上添加3次尝试限制,您可以大大减慢黑客的尝试(甚至是蛮力)。使用任何纯加密,您现在都会遇到另一个问题-保护密钥。如果找到了密钥,则整个数据库将受到威胁(如果未添加盐)。但是,使用散列,您将永远不会从系统中获得原始密码,这就是应该的样子。
凯尔·罗森多

1
如上所述,MD和SHA系列的问题在于它们针对速度进行了优化。随着计算的发展,这种性质的哈希不可避免地变得越来越不安全。
Johannes Gorset'2

1
随着计算的发展,任何事情都变得越来越糟糕/不安全等。到SHA512等被黑客入侵时,将有更多安全算法可用。无论如何,这就是计算的本质。
凯尔·罗森多

1
在php中加盐的好方法是什么?有示例代码?我想我不应该只选择像“长颈鹿”这样的东西
托尼·史塔克2010年

4

人们似乎缺少的是,如果黑客可以访问数据库,那么他可能还可以访问散列密码的php文件,并且很可能会对其进行修改,以向其发送所有成功的用户名密码组合。如果他无权访问Web目录,那么他总是可以选择一个密码对其进行哈希处理,然后将其写入数据库。换句话说,哈希算法实际上与系统安全无关紧要,并且如果您不使用SSL,也可以限制登录尝试,那么攻击者只需侦听连接即可获取信息。除非您需要算法花很长时间(出于您自己的目的)进行计算,否则具有用户特定盐的SHA-256或SHA-512就足够了。

作为一项附加的安全措施,设置脚本(bash,批处理,python等)或程序,并为其指定一个晦涩的名称,并检查它是否已更改login.php(检查日期/时间戳),并向您发送电子邮件如果有的话。还应该记录所有具有管理员权限的登录尝试,并记录所有登录数据库并通过电子邮件发送给您的失败尝试。


“人们似乎缺少的是,如果黑客可以访问数据库,那么他可能还可以访问散列密码的php文件...”这不是事实。SQL注入是最常见的漏洞之一,它可以为数据库提供读/写功能,但对PHP代码的访问权限为零。
ceejayoz 2015年

如果您有权访问该代码,则可以用纯文本格式修改和存储用户发送的所有密码。所以不,如果代码被盗用,那么游戏结束。
magallanes

3

每个人都在谈论这个问题,就像他们可以通过互联网被黑客入侵一样。如前所述,限制尝试使得不可能通过Internet破解密码,并且与哈希无关。

盐是必须的,但是复杂性或多种盐甚至都没有关系。仅靠盐就可以阻止攻击者使用预制的彩虹桌。每个用户的唯一盐会阻止攻击者创建新的Rainbow表以用于整个用户群。

当整个数据库遭到破坏时,安全性才真正发挥作用,然后黑客可以每秒针对md5哈希执行1亿次密码尝试。SHA512慢大约10,000倍。具有当今功能的复杂密码,使用md5进行暴力破解仍可能需要100年,而使用SHA512则需要10,000倍的时间。这些盐根本无法阻止暴力破解,因为它们始终是众所周知的,如果攻击者下载了您的数据库,那么无论如何他都可能在您的系统中。


1

由于冲突问题,MD5不好-两个不同的密码可能会生成相同的md-5。

Sha-1对此非常安全。之所以要存储盐腌的sha-1版本密码,是因为这样一来,您就不会将用户的密码保留在文件中,因为他们可能正在与其他人的服务器一起使用。否则,有什么区别?

如果黑客以某种方式窃取了您整个未加密的数据库,那么哈希密码的唯一作用就是阻止他假冒用户进行将来的登录-黑客已经拥有了数据。

如果您的用户输入的是纯密码,那么拥有哈希值的攻击者有什么用?

即使采用未来技术的黑客每秒可以生成一百万个sha-1密钥进行暴力攻击,您的服务器是否也会每秒处理一百万个登录信息以供黑客测试其密钥?这就是如果您要让黑客尝试使用盐腌的sha-1登录,而不是像正常登录那样使用密码登录。

最好的选择是将错误的登录尝试限制为某个合理的次数-例如25次,然后使用户超时一两分钟。并且,如果累积的不良登录尝试在24小时内达到250次,请关闭帐户访问权限并向所有者发送电子邮件。


即使我使用的是较弱的加密,也几乎没有任何系统可以每秒进行超过一百万次尝试的暴力攻击。
magallanes

1
三次失败的登录,您已被锁定。时期,故事的结尾。如果黑客碰巧先尝试“ password”,“ pa $$ word”和“ passw0rd”,那么即使像“ 1234”这样的超级愚蠢密码也很安全(请锁定!)。用户如何重新获得访问权限现在成为您的安全重点,而您的操作取决于用户群的大小。200个用户?让他们打电话寻求帮助。
UncaAlby

这个答案对其他任何人都没有意义,还是仅我一个人?
通配符


1

使用argon2i。该argon2密码散列函数先后荣获中的密码哈希比赛。

如果不使用argon2,则其他合理的选择是scryptbcryptPBKDF2。维基百科上有以下功能页面:

MD5,SHA1和SHA256是消息摘要,而不是密码哈希函数。它们不适合此目的。

从MD5切换到SHA1或SHA512不会大大提高构造的安全性。计算SHA256或SHA512哈希非常快。具有通用硬件的攻击者仍然可以每秒尝试数千万(使用单个CPU)甚至数十亿(使用单个GPU)哈希。好的密码哈希功能包括降低字典攻击速度的工作因素。

这是对PHP程序员的建议:阅读PHP FAQ,然后使用password_hash()


0

让我们假设下一点:黑客窃取了包括用户和密码(已加密)的数据库。黑客利用他们知道的密码创建了一个伪造帐户。

MD5之所以很弱,是因为它简短而流行,几乎每一个没有密码的哈希生成都很难受到字典攻击。但..

因此,假设我们仍在使用带有SALT的MD5。黑客不知道SALT,但他们知道特定用户的密码。因此他们可以测试:????? 12345,其中12345是知道密码和?????。是盐。黑客迟早可以猜出SALT。

但是,如果我们使用MD5 + SALT并应用了MD5,则无法恢复信息。但是,我重复一遍,MD5仍然很短。

例如,假设我的密码是:12345。SALT是BILLCLINTON

md5:827ccb0eea8a706c4c34a16891f84e7b

带有哈希值的md5:56adb0f19ac0fb50194c312d49b15378

MD5的哈希值位于md5之上:28a03c0bc950decdd9ee362907d1798a我尝试使用这些在线服务,但没有发现能够破解的服务。而且只有MD5!(可能像今天一样会被破解,因为我在线生成了md5)

如果要过度杀伤,则SHA256只需加盐和两次即可。

tldr MD5(HASH + MD5(password))=可以,但很短,SHA256绰绰有余。


将MD5与盐一起使用的问题在于,计算机可以以超快的速度对一个密码进行暴力攻击。shylor.com/2015/09/14/php-5-5-secure-password-hashing
Shylor 2016年

0

md5加密是最糟糕的加密之一,因为您必须旋转代码,并且已经被解密。我向您推荐SHA256。我的编程时间更长一些,并且有很好的经验。下面也将是加密。

password_hash() example using Argon2i

<?php
echo 'Argon2i hash: ' . password_hash('rasmuslerdorf', PASSWORD_ARGON2I);
?>
The above example will output something similar to:

Argon2i hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.