43

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

4

6 回答 6

50

首先,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
了解 sha-1 碰撞弱点

于 2013-02-10T13:40:04.670 回答
3

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

于 2013-02-10T13:39:39.497 回答
2

数据库中的密码应加密存储。建议采用一种加密方式(散列),例如 SHA2、SHA2、WHIRLPOOL、bcrypt DELETED: MD5 或 SHA1。(那些年龄较大,易受伤害的

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

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

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

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

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

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

于 2013-02-10T13:40:31.453 回答
2

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

于 2013-02-10T13:40:56.537 回答
1

最好使用 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

于 2013-02-10T13:42:34.953 回答
0

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

于 2013-02-10T13:43:58.813 回答