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

发布于 2024-08-05 05:59:33 字数 173 浏览 6 评论 0原文

我有一个 LAMP (PHP) 网站,该网站越来越受欢迎。

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

但我现在发现这并不安全;我应该对 md5 哈希值加盐 - 因为目前可以使用彩虹表解码未加盐的 md5 哈希值。

我能做些什么?

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

I have a LAMP (PHP) website which is becoming popular.

I played it safe by storing the user passwords as md5 hashes.

But I now see that's not secure; I should have salted the md5 hash - because it's currently possible to decode unsalted md5 hashes using rainbow tables.

What can I do?

I don't want to make everyone type a new password.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

蓝颜夕 2024-08-12 05:59:33

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

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

通常的腌制过程是

salt+PWD->Salt+PWD。哈希

你可以这样做:
密码 ->哈希->用户ID+哈希->哈希

(请注意,仅选择了 UserID,因此每个双哈希都存在唯一的盐...随意使您的盐更复杂)

You can do a "2 step hashing" instead of creating a hash in a single step.

You could append each password hash to the username, and then hash it again. This will create an undecryptable hash thats salted with unique informations.

The usual process of salting is

salt+PWD -> hash

You could do something like:
PWD -> Hash -> UserID+Hash -> Hash

(Note the UserID was only picked so a unique salt for each double hash exists... Feel free to make your salt more complex)

君勿笑 2024-08-12 05:59:33

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

唯一的问题是,您需要添加一个指示符来指示每个 MD5 是否加盐,因为您将在一段时间内混合使用两者。或者,为了稍微降低安全性,您可以检查每个加盐和未加盐的密码,如果其中一个密码命中,则接受登录。当然,如果您检测到它没有加盐,那么您就可以在此时升级。

You can salt them on the fly. Add a piece of code so that, when someone logs in, it does the normal process (computes the MD5 sum of the password and checks it against the stored hash) and if that succeeds, recompute a salted version of the hash from the clear-text password they entered, and store it in the password file.

The only wrinkle is that you'll need to add an indicator for whether each MD5 is salted or not, since you'll have a mix of both for a while. Or, for a minor loss of security, you can check each password salted and unsalted and if either one hits, accept the login. Of course, if you detect that it was unsalted, then you upgrade at that point.

红衣飘飘貌似仙 2024-08-12 05:59:33

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

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

The answer is simple, make sure the keep a record or some sort of flag of which users have passwords on the new system of hashing, when they next login, authenticate them, calculate the new hash, flip the flag.

Now whenever someone logs in and the flag is set, authenticate them with the new hash.

为你鎻心 2024-08-12 05:59:33

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

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

Why not add a new column new_pwd to your user table, which stores the result of md5($originallyHashOfPwd . $salt). You can then precompute new_pwd and once that's done adjust your login checking to compare the result of md5(md5($entered_pwd) . $salt) to what's in new_pwd. Once you're done switching your login checking, delete the old column.

That should stop rainbow-table style attacks.

惯饮孤独 2024-08-12 05:59:33

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

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

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

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

You can still use a salt. Just calculate another hash from the current hash together with a salt:

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

For new passwords you then need to use:

$hash = md5($salt.md5($password));
美胚控场 2024-08-12 05:59:33

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

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

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

A great way to update the passwords while also making them more secure is to change to using a salted SHA1 for passwords. A SHA1 is harder to create a collision against, and it also has a different string length to MD5. A MD5 is 32 characters long, while a SHA1 is 40 characters long.

To convert these in PHP, you first check the string length of the stored password. If it is 32 characters long, check the password using your old method and afterwards, write a new one using SHA1 to the database.

If I remember correctly, this is precisely how WordPress handled this issue.

海的爱人是光 2024-08-12 05:59:33

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

Dynamically re-encrypt the passwords when the users log in the next time, i.e. first check whether it’s correct, afterwards encrypt it with a salt and store it again.

凡间太子 2024-08-12 05:59:33

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

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

You can migrate the passwords by adding a column in your tables to store the new format.

When a user logs in successfully, if the new column is empty, put the stronger password in there and empty out the original column. If the new column has an entry, compare the input to the value in there.

简单气质女生网名 2024-08-12 05:59:33

这里有两个选项

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

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

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

Two options here

  • Decode the passwords yourself, and re-encode them with a salt (I recommend something a little more fancy than MD5). You should inform the users that you're viewing their passwords unencrypted. It'll probably take a lot of time as well.
  • Make them retype their passwords, and store those salted and encrypted.

As far as I can see, there is no other way of recovering the passwords.

EDIT:
Although MD5 is a hash and should not be decodable, it can be broken using rainbow tables: with probability almost one, you can find a unique (here's the probability) string of at most, say, 20 characters with a given hash, especially if your character set is limited, say, to alphanumeric. Strictly speaking, this is not decoding. For all practical purposes, it is.
Extra note: producing the rainbow tables, and looking up 1000 password is still going to take a lot of time.

﹉夏雨初晴づ 2024-08-12 05:59:33

正如其他人提到的,对原始哈希加盐。这里有几点提示:

  • 盐越长越好。另外,如果它们包含的内容多于[a-z0-9],但首先长度更好。
  • 如果某人已经拥有您的数据库的副本,并且您使用 salt 重新哈希相同的密码,则使用 salt 重新哈希旧哈希将不起作用。相反,您确实应该强制用户设置新密码。
  • 您应该将新密码(以及要加盐的密码)与最常用密码的各种列表进行匹配。这些用于“暴力”攻击。提示/强制用户更改密码。

Salt the original hash as mentioned by others. Just a few pointers here:

  • Salts are better the longer they are. Also if they contain more then just [a-z0-9] but length is better first of all.
  • If someone already has a copy of your DB and you rehash the same passwords with salt, the rehash the old hash with salt will not work. Instead you really should force users to make a new password.
  • You should match new passwords (and passwords to be salted) up against various lists of the most commonly used passwords. These are used in "brute force" attacks. Prompt/force the user to change the password.
是伱的 2024-08-12 05:59:33

如果您要放弃 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) 来查看密码是否正确

If you're moving away from MD5, you should go skip simply salting and go to an even better technique called stretching. In particular you should use bcrypt (implemented as PHPASS with php).

Here is a great link on why bcrypt: http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html

And here is a short How To:
1. Download the phpass package: http://www.openwall.com/phpass/
2. Look at test.php for examples like the one below:

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

If $check===true (which is the case above) then the password is correct.
If your password is 'hello', you would hash it using HashPassword, put the hash in a database, and when a user logs in, call CheckPassword(userenteredpassword,hashInDb) to see if the password is correct

混浊又暗下来 2024-08-12 05:59:33

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

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

编辑

您可以对存储的密码进行双重编码。因此,您的新加盐哈希算法将是:

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
}

sadly, your only way is to tell your users to renew their passwords.

you could also generate random passwords, but that is the same hassle.

edit

you could just double encode your stored passwords. so your new salted hashing algorithm would be:

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

to update your old passwords use

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

to check if a provided password is correct simply use

list($stored_password, $salt) = explode(':', $salted_password);
if(md5(md5($provided_password).$salt) == $stored_password) {
  // you are now logged in
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文