从无盐保证到盐渍MD5密码

时间:2009-09-22 12:51:58

标签: php md5

我有一个LAMP(PHP)网站正在变得流行。

我通过将用户密码存储为md5哈希来保证安全。

但我现在看到这不安全;我应该腌制md5哈希 - 因为它目前可以使用彩虹表解码未加盐的md5哈希。

我该怎么办?

我不想让每个人都输入新密码。

12 个答案:

答案 0 :(得分:21)

您可以执行“2步哈希”,而不是一步创建哈希。

您可以将每个密码哈希附加到用户名,然后再次哈希。这将创建一个不可加密的哈希,其中包含独特的信息。

通常的腌制过程是

盐+ PWD - >散列

你可以这样做: PWD - >哈希 - > UserID + Hash - >哈希

(注意,只选择了UserID,因此每个双哈希存在一个唯一的盐...随意让你的盐变得更复杂)

答案 1 :(得分:10)

你可以动态加盐。添加一段代码,以便当有人登录时,它执行正常过程(计算密码的MD5总和并根据存储的哈希检查它),如果成功,则从清除中重新计算哈希的盐渍版本输入的文本密码,并将其存储在密码文件中。

唯一的缺点是你需要添加一个指示器来确定每个MD5是否都被腌制,因为你可能会混合使用一段时间。或者,对于轻微的安全性损失,您可以检查每个密码和未加密的密码,如果有任何一个命中,请接受登录。当然,如果您发现它是未加盐的,那么您将在那时进行升级。

答案 2 :(得分:6)

答案很简单,请确保在新的哈希系统上保留记录或某种用户标记的标记,下次登录时,验证它们,计算新哈希,翻转标记。

现在每当有人登录并设置了标志时,请使用新哈希对其进行身份验证。

答案 3 :(得分:5)

为什么不在您的用户表中添加新列new_pwd,该列存储md5($originallyHashOfPwd . $salt)的结果。然后,您可以预先计算new_pwd,一旦完成,请调整您的登录检查,以将md5(md5($entered_pwd) . $salt)的结果与new_pwd中的结果进行比较。完成登录检查后,请删除旧列。

这应该可以阻止彩虹表式攻击。

答案 4 :(得分:4)

你仍然可以使用盐。只需从当前哈希中计算另一个哈希值和盐:

$newHash = md5($salt.$oldHash);

对于新密码,您需要使用:

$hash = md5($salt.md5($password));

答案 5 :(得分:1)

更新密码同时使密码更安全的一种好方法是更改​​为使用盐渍SHA1密码。 SHA1更难创建碰撞,并且它与MD5的字符串长度也不同。 MD5长度为32个字符,而SHA1长度为40个字符。

要在PHP中转换它们,首先要检查存储密码的字符串长度。如果长度为32个字符,请使用旧方法检查密码,然后使用SHA1将新密码写入数据库。

如果我没记错的话,这正是WordPress处理这个问题的方式。

答案 6 :(得分:0)

这里有两个选项

  • 自己解码密码,并用盐重新编码(我推荐的东西比MD5更有趣)。您应该通知用户您正在查看未加密的密码。这可能也需要很长时间。
  • 让他们重新输入密码,并存储加密和加密的密码。

据我所见,没有其他方法可以恢复密码。

编辑: 虽然MD5是一个哈希值,不应该是可解码的,但它可以使用彩虹表来破解:概率几乎为1,你可以找到一个唯一的(这里是概率)字符串,最多比如20个字符和给定的哈希,特别是如果你的字符集仅限于字母数字。严格来说,这不是解码。出于所有实际目的,它是。 额外注意:制作彩虹表,查找1000密码仍然需要很多的时间。

答案 7 :(得分:0)

当用户下次登录时动态重新加密密码,即首先检查密码是否正确,然后用盐加密并再次存储。

答案 8 :(得分:0)

您可以通过在表格中添加一列来存储新格式来迁移密码。

当用户成功登录时,如果新列为空,请将更强的密码放在那里并清空原始列。如果新列有一个条目,请将输入与其中的值进行比较。

答案 9 :(得分:0)

如其他人所述,将原始哈希加盐。这里只需几点:

  • 盐越长越好。如果它们包含更多,那么只需要[a-z0-9],但首先长度更好。
  • 如果某人已经拥有您的数据库的副本并且您使用salt重新使用相同的密码,那么使用salt重新散列旧的哈希将不起作用。相反,你真的应该强迫用户制作一个新密码。
  • 您应该将新密码(和要加密的密码)与最常用密码的各种列表相匹配。这些用于“暴力”攻击。提示/强制用户更改密码。

答案 10 :(得分:0)

如果你正在远离MD5,那么你应该跳过简单的腌制,然后采用一种更好的拉伸技术。特别是你应该使用bcrypt(用PHP实现为PHPASS)。

以下是bcrypt:http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html

的绝佳链接

以下是如何: 1.下载phpass包:http://www.openwall.com/phpass/ 2.查看test.php,了解如下例子:

require 'PasswordHash.php';
$t_hasher = new PasswordHash(8, FALSE);
$correct = 'plaintextpassword';
$hash = $t_hasher->HashPassword($correct);
$check = $t_hasher->CheckPassword($correct, $hash);

如果$ check === true(上面就是这种情况),那么密码是正确的。 如果您的密码是'hello',您可以使用HashPassword对其进行哈希处理,将哈希值放入数据库中,当用户登录时,调用CheckPassword(userenteredpassword,hashInDb)以查看密码是否正确

答案 11 :(得分:-1)

遗憾的是,你唯一的办法是告诉用户更新密码。

你也可以生成随机密码,但这也是一样的麻烦。

修改

您可以对存储的密码进行双重编码。所以你的新盐渍哈希算法将是:

md5(md5($new_password).$salt).':'.$salt

使用

更新旧密码
md5($old_password.$salt).':'.$salt

检查提供的密码是否正确,只需使用

即可
list($stored_password, $salt) = explode(':', $salted_password);
if(md5(md5($provided_password).$salt) == $stored_password) {
  // you are now logged in
}