Salting密码PHP,MySQL

时间:2011-04-17 21:31:24

标签: php mysql security

以下是盐密码的好方法吗?

hash('sha256', $_POST['password'], $_POST['email'])

我使用用户电子邮件作为盐。有些人不使用电子邮件,有些人则说使用随机数。

即使我使用随机数,我仍然需要将它存储在我的MySQL表中,所以无论如何盐仍然是已知的,并且使用电子邮件的额外好处是彩虹表的可能性大大降低,即使我要使用16位整数?

5 个答案:

答案 0 :(得分:8)

盐背后的想法是防止黑客使用彩虹表。例如,如果黑客能够破坏您的数据库并找出散列密码是什么,他就不能轻易地对散列进行反向工程以找到会产生相同散列的值。

但是,存在称为彩虹表的已经散列的单词表。有些人已经经历了计算字典中每个单词的散列和其他常用密码的麻烦。如果黑客拥有这些表中的一个,加上数据库中的哈希密码,则可以很容易地找出密码是什么。

然而,一个salt改变了所有这一切,因为现在,你不是哈希密码,而是哈希密码加上一些随机值,这意味着彩虹表现在没用了。黑客是否可以妥协盐无关紧要。

将盐以明文保存是完全没问题的。你想要在所有用户之间使用一些不统一的东西,因为这又失败了。我个人喜欢使用帐户创建的时间戳。

这有意义吗?

答案 1 :(得分:4)

如果用户更改了自己的电子邮件地址会怎样?您将无法再验证他/她的密码,因为盐值将消失。

你不应该使用任何可能随时间变化的盐。生成随机盐(足以打败彩虹表)并与密码一起使用以生成散列。

答案 2 :(得分:1)

现在,在PHP中使用密码散列的最佳解决方案是使用bcrypt(blowfish)实现。为什么?有几个原因:

  • 变量'work'参数
  • 内置盐

请记住,如果您没有运行php 5.3,那么您的系统可能无法使用crypt_blowfish。

工作参数

Blowfish / crypt已经有一个昂贵的设置时间,但通过设置工作因素,您可以增加计算哈希所需的时间。此外,随着计算机变得更快并且能够更轻松地计算哈希值,您可以在将来轻松更改该工作因素。这使得特定的散列方法可以扩展。

内置盐

对我而言,这只是懒惰,但我喜欢盐和&传球存放在一起。

实施

要使用blowfish,您可以按如下方式创建哈希

// salts must be 22 characters
$salt = "ejv8f0w34903mfsklviwos";

// work factor: 04-31 (string), each increase doubles the processing time.
// 12 takes my current home computer about .3 sec to hash a short string
$work = '12';

// $2a$ tells php to use blowfish
// you end up with a string like '$2a$12$mysalthere22charslong'
$options = '$2a$' . $work . '$' . $salt;

$hashedPass = crypt($plaintext, $options);

验证散列密码是否简单:

if(crypt($user_input, $stored_password) == $stored_password) { echo "valid!"; }

现在,如果您想在任何特定时间增加工作因素,您可以在成功登录后获取提交的通行证,然后重新发送并保存。因为工作因素与盐和盐一起保存。密码,更改对系统的其余部分是透明的。

修改

关于河豚是双向加密密码的评论似乎有些混乱。它没有在crypt中实现。 bcrypt是一种自适应密码散列算法,它使用Blowfish密钥时间表,而不是对称加密算法。

你可以在这里阅读所有相关内容:http://www.usenix.org/events/usenix99/provos.html

或者你可以在这里阅读更多关于使用bcrypt(河豚的哈希实现)的信息:http://codahale.com/how-to-safely-store-a-password/

答案 3 :(得分:0)

我建议使用如下所示的迭代。可以用md5或任何其他散列算法替换crypt。 10可以是任何数字。

$pass=mysql_real_escape_string($_POST['pass']);

$iterations = 10;
$hash = crypt($pass,$salt);
for ($i = 0; $i < $iterations; ++$i)
{
  $password = crypt($hash . $pass,$salt);
}

此外,您还可以添加任何其他变量。我希望这能解决问题

答案 4 :(得分:-1)

你可以用这个:

$salt='whatever';
$a=hash('sha256', $_POST['password'], $salt);
$b=hash('sha256', $_POST['email'], $salt);
$hash=$a.'-'.$b;

当用户更改电子邮件时,只需执行以下操作:

$old_a=substr($old_hash,0,strpos($old_hash,'-'));
$new_b=hash('sha256', $_POST['email'], $salt);
$new_hash=$old_a.'-'.$new_b;