首页 文章

从无盐保证到盐渍MD5密码

提问于
浏览
20

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

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

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

我能做什么?

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

12 回答

  • 1

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

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

  • 0

    这里有两个选择

    • 自己解码密码,并用盐重新编码(我推荐的东西比MD5更有趣) . 您应该通知用户您可能也需要花费很多时间 .

    • 让他们重新输入密码,并存储盐渍和加密的密码 .

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

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

  • 0

    您可以执行“两步散列”,而不是一步创建散列 .

    您可以将每个密码哈希附加到用户名,然后再次哈希 . 这将创建一个不可加密的哈希值,该哈希值具有独特的信息 .

    通常的腌制过程是

    salt PWD - >哈希

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

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

  • -1

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

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

  • 0

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

    现在,只要有人登录并设置了标志,请使用新哈希对其进行身份验证 .

  • 0

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

    这应该会阻止彩虹表式攻击 .

  • 21

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

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

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

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

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

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

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

  • 10

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

  • 0

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

    • 盐越长越好 . 如果它们包含更多,那么只需要[a-z0-9],但首先长度更好 .

    • 如果某人已经拥有您的数据库的副本并且您使用salt重新使用相同的密码,则使用salt重新散列旧的哈希将不起作用 . 相反,你真的应该强迫用户制作一个新密码 .

    • 您应该将新密码(和要加密的密码)与最常用密码的各种列表相匹配 . 这些用于"brute force"攻击 . 提示/强制用户更改密码 .

  • 4

    如果你正在远离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)来查看密码是否正确

  • 6

    遗憾的是,您唯一的方法是告诉用户更新密码 .

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

    edit

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

    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
    }
    

相关问题