这是存储密码的安全方法吗?

时间:2011-11-04 05:42:11

标签: php security encryption hash passwords

我一直在阅读有关此主题的一些不同的指南/教程,并发现了以下内容:

我知道我所阅读的内容是一种非常安全的方式来存储用户密码。我尝试将2稍微合并而不是像第一个例子中那样使用mt_rand,我已经生成了自己的动态盐。

这是我的代码:

<?php

    $static_salt = ""; // Removed value for obvious reasons

    $dynamic_salt_choice = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $dynamic_salt_length = 40;

    $dynamic_salt = "";

    $dynamic_salt_max = strlen($dynamic_salt_choice)-1;

    for ($i = 0; $i < $dynamic_salt_length; $i++) {

        $dynamic_salt .= substr($dynamic_salt_choice, rand(0, $dynamic_salt_max), 1);

    }

    $password_length = length($password);
    $split_at = $password_length / 2;
    $password_array = str_split($password, $split_at);

    $password = $password_array[0] . $static_salt . $password_array[1];

    $password_hash = hash_hmac('sha512', $password, $dynamic_salt);

?>

根据我的说法,这是获取静态盐,生成动态盐,然后我们将给定的密码分成2个部分放在一个数组中,并在两个密码部分之间添加静态盐。

然后我们使用sha12和动态盐一起散列密码。

我的问题是,这是否比我链接的两种方法更安全或更安全?或者我通过这种方式混合起来让它变得更加脆弱?

我还把它$password_hash存放在一个cookie中,用户名cookie旁边的自动登录是一个很大的禁忌?如果是这样,网站如何以安全的方式通过cookie记住您?

4 个答案:

答案 0 :(得分:2)

  

我正在努力提高我的网站的安全级别

嗯,为了让您知道,没有密码哈希问题可以提高您的网站安全性 您必须关注其他更重要的事情,例如SQL和文件注入,XSS和CSRF漏洞。 如果您确保网站安全,它会保护您的密码安全,只是副作用。

接下来你需要关注的是密码强度无哈希可以保护愚蠢的密码,例如joe123

至于散列本身 - 你可以使用你想要的任何东西,一些基本的东西,如使用一些理智的盐,如注册时间或电子邮件和任何哈希函数的一些迭代就足够了。不要在散列中加入太多含义。发明一些额外安全的原始算法并不需要太多关注。

  

我的问题是,这是否比我链接的两种方法更安全或更安全?或者我通过这种方式混合起来让它变得更加脆弱?

Dunno,如果你相信我(我打赌你不会),但所有这些方法都足够安全,不需要任何改变。并且影响网站的安全性,但只有密码本身,以防他们使用您网站中的其他漏洞被盗

  

我还把它存储在一个cookie中的$ password_hash与用户名cookie一起用于自动登录是一个很大的禁忌?

我认为揭示哈希本身并不明智。但同样,它不会影响网站安全,只会影响潜在的漏洞。如果你的哈希和密码足够强大,一个逻辑让我说它足够安全。

答案 1 :(得分:1)

这似乎是一个合理的腌制方案,虽然可能有点过分。它可能不需要长达40个字符 - 你只是试图炸掉彩虹桌的大小,而不是制作一个不可思议的nonce - 但是长时间不会受到伤害。

对于自动登录,您应该(在cookie中)存储一个随机令牌,该令牌对应于指向用户帐户的数据库条目。当用户更改其密码时,请清除该用户的所有这些条目。生成此令牌时,rand()不够好 - 您需要一个安全不可取的随机数。不幸的是,PHP并没有真正的安全随机数的内置工具 - mt_rand()差不多,但我个人会在Linux系统上直接从/dev/urandom读取随机字节,用它来生成我的随机数。

答案 2 :(得分:1)

假设$dynamic_salt与最终$password_hash一起存储 - 因为没有它就不能测试哈希 - 这个方案非常弱。使用salt确实可以防止彩虹表,但是非迭代的HMAC使这种方案对于暴力攻击都很弱。 (盐的长度对你没有好处,因为它是哈希输入中的一个已知常量。将它放在原始密码的中间也没有用。)

总的来说,这个方案远远弱于bcrypt(),因为它只(有效地)迭代两次哈希。你真的没有比使用更简单的方案存储密码更好,例如:

$salt = uniqid();
$password_hash = hash_hmac('sha512', $password, $salt);

但是你最好还是使用别人的(经过测试和验证的)密码加密程序,而不是自己烹饪。


关于在cookie中使用密码哈希 - 这是应该避免的,因为它允许攻击者以只读方式访问数据库(例如,通过SQL注入攻击或被盗备份)在不知道或更改密码的情况下冒充应用程序中的任何用户。这也意味着,如果用户的计算机已设置为自动登录,则密码哈希值将存储在其中。我会避免这种情况。

更好的方案可能是在用户选择自动登录时在cookie中设置随机生成的nonce,然后将该nonce的哈希值存储在数据库中。这样,服务器可以检查登录密钥的正确性,而无需“记住”它。

答案 3 :(得分:0)

可以使用盐,但它有其自身的局限性。另一种方法是使用bcrypt.More信息可以在http://www.openwall.com/phpass/

找到

我认为这篇SO文章绰绰有余Secure hash and salt for PHP passwords