Php 从未加盐的MD5密码变为加盐的MD5密码

Php 从未加盐的MD5密码变为加盐的MD5密码,php,md5,Php,Md5,我有一个LAMP(PHP)网站,它正变得越来越流行 为了安全起见,我将用户密码存储为md5哈希 但我现在明白了这并不安全;我应该在md5散列中加盐,因为目前可以使用rainbow表对未加盐的md5散列进行解码 我能做什么 我不想让每个人都输入新密码。遗憾的是,你唯一的办法就是告诉你的用户更新他们的密码 您也可以生成随机密码,但这也是同样的麻烦 编辑 您可以对存储的密码进行双重编码。因此,您的新salted散列算法将是: md5(md5($new_password).$salt).':'.$sal

我有一个LAMP(PHP)网站,它正变得越来越流行

为了安全起见,我将用户密码存储为md5哈希

但我现在明白了这并不安全;我应该在md5散列中加盐,因为目前可以使用rainbow表对未加盐的md5散列进行解码

我能做什么


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

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

您也可以生成随机密码,但这也是同样的麻烦

编辑

您可以对存储的密码进行双重编码。因此,您的新salted散列算法将是:

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
}
这里有两种选择

  • 自己解码密码,然后用salt重新编码(我推荐一些比MD5更花哨的东西)。您应该通知用户您正在查看未加密的密码。这可能也需要很多时间
  • 让他们重新输入他们的密码,并存储那些加密的密码
据我所知,没有其他方法可以恢复密码

编辑: 虽然MD5是一个散列,不应该是可解码的,但它可以使用彩虹表进行分解:概率几乎为1,在给定的散列中,您可以找到一个最多(比如)20个字符的唯一字符串,特别是如果您的字符集被限制(比如)为字母数字。严格地说,这不是解码。就所有实际目的而言,它是。 额外注意:生成rainbow表和查找1000密码仍然需要很多时间。

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

您可以将每个密码散列附加到用户名,然后再次对其进行散列。这将创建一个不可加密的散列,其中包含唯一的信息

通常的腌制过程是

salt+PWD->hash

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


(注意,用户ID只是为了每个双哈希都有一个唯一的salt而被选中的……请随意使salt更复杂)

为什么不在用户表中添加一个新列
new\u pwd
,该列存储
md5($originallyHashOfPwd.$salt)的结果
。然后,您可以预计算
new\u pwd
,完成后调整登录检查,将
md5(md5($entered\u pwd.$salt)
的结果与
new\u pwd
中的内容进行比较。切换登录检查后,删除旧列


这将阻止彩虹桌式攻击。

你可以在飞行中给它们加盐。添加一段代码,以便当有人登录时,它执行正常的过程(计算密码的MD5和,并对照存储的哈希进行检查),如果成功,则根据他们输入的明文密码重新计算哈希的附加版本,并将其存储在密码文件中


唯一的问题是,您需要添加一个指示符来指示每个MD5是否是盐腌的,因为您将在一段时间内混合使用这两种。或者,对于轻微的安全性损失,您可以检查每个加盐和不加盐的密码,如果其中一个被点击,则接受登录。当然,如果您检测到它是未加盐的,那么您可以在该点升级。

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

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

$newHash = md5($salt.$oldHash);
对于新密码,您需要使用:

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

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


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

答案很简单,请确保在新的哈希系统上保留一条记录或某种标志,用户拥有该标志的密码,当他们下次登录时,对其进行身份验证,计算新哈希,翻转该标志


现在,无论何时有人登录并设置了标志,都要使用新的散列对其进行身份验证。

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

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


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

像其他人提到的那样对原始哈希进行盐分。这里只有几点提示:


  • 盐越久越好。此外,如果它们的含量超过[a-z0-9],但首先长度更好
  • 如果某人已经有了你的数据库副本,而你用salt重新设置了相同的密码,那么用salt重新设置旧的哈希将不起作用。相反,您确实应该强制用户创建新密码
  • 您应该将新密码(以及要添加的密码)与各种最常用的密码列表相匹配。这些用于“暴力”攻击。提示/强制用户更改密码

如果你正在远离MD5,你应该跳过简单的盐腌,转而使用一种更好的技术,称为拉伸。尤其应该使用bcrypt(通过php实现为PHPASS)

下面是一个关于为什么使用bcrypt的链接:

下面是一个简短的方法: 1.下载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(如上所示),则passwor