在MYSQL数据库中存储密码的最佳方法[重复]

Posted

技术标签:

【中文标题】在MYSQL数据库中存储密码的最佳方法[重复]【英文标题】:Best way to store passwords in MYSQL database [duplicate] 【发布时间】:2013-01-25 17:40:10 【问题描述】:

是的,我知道不建议以纯文本形式存储密码。是否有一种最佳且简单的方法来存储密码以保证应用程序的安全??

【问题讨论】:

我以为这和this question差不多。 owasp.org/index.php/Password_Storage_Cheat_Sheet php.net/manual/en/faq.passwords.php 使用密码散列函数对密码进行散列并存储。使用 SHA-2 或 SHA-3。 MD5 仍然可以使用,但我建议按照建议继续使用其他 2 个。 使用 bcrypt,这是一种专为密码设计的最先进的散列算法。 This answer 到一个相关问题显示了一种简单的实现方法。 【参考方案1】:

sha1 和 md5 等哈希算法不适用于密码存储。它们的设计非常高效。这意味着暴力破解非常快。即使黑客获得了您散列密码的副本,暴力破解也很快。如果您使用盐,它会使彩虹表的效果降低,但对蛮力没有任何作用。使用较慢的算法会使蛮力无效。例如,bcrypt 算法可以随心所欲地变慢(只需更改工作因子),并且它在内部使用盐来防止彩虹表。如果我是你,我会采用这种方法或类似方法(例如 scrypt 或 PBKDF2)。

【讨论】:

如果我错了,请纠正我,但 SHA1 和 MD5 在防冲突方面被破坏(找到 2 个输入到产生相同哈希的哈希函数),但对于原像仍然可以攻击(给定一个散列找到一些散列到给定值的输入)。只要我们正确地加盐密码,我认为使用 SHA1 或 MD5 没有任何顾虑。 我不是安全专家,所以我也可能是错的:SHA1 和 MD5 速度非常快,因此暴力破解速度非常快——即使您使用的是 salt。确实,使用盐是一个好主意,因为它可以防止彩虹表,但在暴力破解方面,它仍然很脆弱。当使用较慢的算法时,暴力破解是不可行的,因为破解密码需要很长时间。 您可能认为它的计算速度更快是正确的,但我仍然怀疑与 MD5/SHA1 相比,计算最新加密算法的速度有多慢。 好吧,如果您有疑问,为什么不阅读论文并自己评估呢? tarsnap.com/scrypt/scrypt.pdf‎ github.com/DomBlack/php-scrypt - scrypt 的 PHP 实现【参考方案2】:

首先,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 密码(注意:要获得更多可定制性,您需要查看此How do you use bcrypt for hashing passwords in PHP?):

crypt($password, $salt);

盐通常是一个随机字符串,当您对密码进行哈希处理时,您将其添加到所有密码的末尾。使用盐意味着如果有人获取了您的数据库,他们将无法检查散列以获取常用密码。使用彩虹表调用检查数据库。散列时应始终使用盐!

以下是我对 SHA1 和 MD5 碰撞攻击漏洞的证明:http://www.schneier.com/blog/archives/2012/10/when_will_we_se.html、http://eprint.iacr.org/2010/413.pdf、http://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdf、http://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdf 和 Understanding sha-1 collision weakness

【讨论】:

碰撞攻击意味着找到2个具有相同哈希的输入(并且受到生日悖论)。跟这个有关系吗? (因为这对攻击者来说更像是一次原像攻击——当他们得到数据库的转储时)。 crypt 函数最多只能加密 8 个字符。加密 helloworld 和 helloworldearth 返回相同的输出。【参考方案3】:

数据库中的密码应加密存储。 推荐一种方式加密(散列),如SHA2、SHA2、WHIRLPOOL、bcrypt 已删除:MD5 或 SHA1。 (那些年长的,脆弱的

除此之外,您还可以使用额外的每个用户生成的随机字符串 - 'salt':

$salt = MD5($this->createSalt());

$Password = SHA2($postData['Password'] . $salt);

createSalt() 在这种情况下是一个从随机字符生成字符串的函数。

编辑: 或者,如果您想要更高的安全性,您甚至可以添加 2 种盐: $盐1。 $通行证。 $salt2

您可以采取的另一项安全措施是用户停用:在 5 次(或任何其他次数)错误登录尝试后,用户被阻止 x 分钟(假设为 15 分钟)。 它应该最大限度地减少暴力攻击的成功率。

【讨论】:

你应该真的使用bcrypt - 在现代 gfx 卡上使用每秒可以计算 60 亿次的加密哈希值来存储密码是不好的。跨度> "如果您想要更高的安全性,您甚至可以添加 2 个盐:$salt1 . $pass . $salt2" 没有坏处,但是添加更多的盐并没有安全收益。当然salt长度不应该小,但是这种情况下md5的128位就足够了(see also this question) 是的,但它更像是密码 - 如果您的密码中有 1 个大写字母,最好将其放在密码的中间,而不是作为第一个/最后一个字符(与数字或任何其他特殊字符)。【参考方案4】:

为用户存储一个唯一的盐(例如从用户名 + 电子邮件生成),并存储一个密码。登录时,从数据库中获取 salt 并哈希 salt + 密码。使用 bcrypt 对密码进行哈希处理。

【讨论】:

【参考方案5】:

最好使用 crypt 将密码存储在数据库中

示例代码:

$crypted_pass = crypt($password);

//$pass_from_login is the user entered password
//$crypted_pass is the encryption
if(crypt($pass_from_login,$crypted_pass)) == $crypted_pass)

   echo("hello user!")

文档:

http://www.php.net/manual/en/function.crypt.php

【讨论】:

【参考方案6】:

您应该使用单向加密(这是一种加密值的方法,因此很难反转它)。我对 mysql 不熟悉,但快速搜索表明它有一个 password() 函数,正是这种加密。在数据库中,您将存储加密的值,当用户想要验证您提供的密码时,您使用相同的算法/函数对其进行加密,然后检查该值是否与存储在数据库中的密码相同那个用户。这假设浏览器和您的服务器之间的通信是安全的,即您使用 https。

【讨论】:

不,MySQL PASSWORD() 函数仅供内部使用,不应依赖。 MySQL 中有散列函数,但在 SQL 中进行散列是一个坏主意。密码很容易通过查询日志暴露。

以上是关于在MYSQL数据库中存储密码的最佳方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在.net core mvc应用程序上存储用户密码的最佳方法[重复]

存储 oauth 和本地身份验证方法的最佳实践?

当 API 调用需要以纯文本形式发送密码时,将密码存储在数据库中的最佳方法是啥?

linux中mysql如何实现免密码登录

数据库的最佳+最强加密方法[关闭]

加密密码php的最佳方式(2017年)[重复]