php 使用密码作为盐的 md5 哈希?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5482437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
md5 hashing using password as salt?
提问by wiiman
md5($password.md5($password))
is this good enough for password hashing? I am not asking for comparing this to something like bcrypt.
这对于密码散列是否足够好?我不是要求将它与 bcrypt 之类的东西进行比较。
if it is not secure, tell me why.
如果它不安全,请告诉我原因。
回答by Don Kirkby
The reason to use a different salt for each user's password is so that an attacker can't take a list of all the hashed passwords and see if any of them match the hash of something easy like "password" or "12345". If you were to use the password itself as salt, then an attacker could calculate md5("12345".md5("12345"))
and see if it matched any entries.
为每个用户的密码使用不同的 salt 的原因是,攻击者无法获取所有散列密码的列表,并查看它们中的任何一个是否与诸如“password”或“12345”之类的简单内容的散列匹配。如果您将密码本身用作盐,那么攻击者可以计算md5("12345".md5("12345"))
并查看它是否与任何条目匹配。
As I understand it, there are four levels of hashing you can use on a password table:
据我了解,您可以在密码表上使用四个级别的散列:
- None- store the password as plain text. If someone gets a copy of your database, they have access to all accounts. Plain text is bad, 'mkay?
- Hash the password- store the hash of the password, and throw away the real password. If someone gets a copy of your database, they can't see any passwords, only hashes. However, if any users have used weak passwords, then their hashes will appear in rainbow tables. For example, if a user has the password "password", then an md5 hash stored in the database would be "5f4dcc3b5aa765d61d8327deb882cf99". If I look up that hash in a rainbow table like the one at gromweb.com, it spits out "password".
- Use a salt value- choose a large random string like a GUID and store it in your configuration file. Append that string to every password before calculating a hash. Now the rainbow table is far less likely to work because it probably won't have an entry for "password59fJepLkm6Gu5dDV" or "picard59fJepLkm6Gu5dDV". Although precalculated rainbow tables are not as effective anymore, you can still be susceptible if the attacker knows your salt value. The attacker can calculate the hash of a weak password plus your salt and see if any user in your databaseuses that weak password. If you've got several thousand users, then each hash calculation lets the attacker make several thousand comparisons. How you actually use the salt may depend on the encryption algorithm you're using. For simplicity, just imagine it as appending the salt and the password together.
- Use a distinct salt value- now you take something distinct like the user name, e-mail address, or even user id, and combine that with the password and the large random string from your configuration file before you calculate the hash. Now an attacker who knows your salt still has to recalculate the hash for every user to see if they have used a weak password like "password".
- 无- 将密码存储为纯文本。如果有人获得了您的数据库的副本,则他们可以访问所有帐户。纯文本不好,'mkay?
- 散列密码- 存储密码的散列,并丢弃真正的密码。如果有人获得了您数据库的副本,他们将看不到任何密码,只能看到哈希值。但是,如果任何用户使用了弱密码,那么他们的哈希值将出现在彩虹表中。例如,如果用户有密码“password”,那么存储在数据库中的 md5 哈希值将是“5f4dcc3b5aa765d61d8327deb882cf99”。如果我在 gromweb.com 上的彩虹表中查找该哈希,它会吐出“密码”。
- 使用盐值- 选择一个大的随机字符串,如 GUID 并将其存储在您的配置文件中。在计算哈希之前将该字符串附加到每个密码。现在彩虹表不太可能工作,因为它可能没有“password59fJepLkm6Gu5dDV”或“picard59fJepLkm6Gu5dDV”的条目。尽管预先计算的彩虹表不再那么有效,但如果攻击者知道您的盐值,您仍然很容易受到影响。攻击者可以计算弱密码加上你的盐的哈希值,看看你的数据库中是否有任何用户使用那个弱密码。如果你有几千个用户,那么每次哈希计算都会让攻击者进行几千次比较。您实际使用盐的方式可能取决于您使用的加密算法。为简单起见,将其想象为将盐和密码附加在一起。
- 使用不同的盐值- 现在您可以使用不同的东西,例如用户名、电子邮件地址,甚至用户 ID,并在计算哈希之前将其与密码和配置文件中的大随机字符串结合起来。现在,知道您的 salt 的攻击者仍然必须重新计算每个用户的哈希值,以查看他们是否使用了像“password”这样的弱密码。
For more details, check out the Coding Horror post, "You're probably storing passwords incorrectly".
有关更多详细信息,请查看 Coding Horror 帖子“您可能存储的密码不正确”。
回答by Your Common Sense
Although it seems quite enough to me, it will be in danger in case if someone precomputed a rainbow table based on the same algorithm (what is quite possible). So, I'd rather use an email for the salt which seems pretty secure yet usable. Paranoids may addsome constant site-wide salt.
虽然对我来说似乎已经足够了,但如果有人根据相同的算法预先计算出彩虹表(这很有可能),那将会有危险。所以,我宁愿使用电子邮件来获取盐,它看起来非常安全但可用。偏执狂可能会添加一些恒定的站点范围的盐。
People often makes too big deal out of password salt (in theory), while in their applications they allow simple passwords and transfer them in plain text over insecure HTTP in practice.
人们经常把密码盐分得太多(理论上),而在他们的应用程序中,他们允许简单的密码,并在实践中通过不安全的 HTTP 以纯文本形式传输它们。
Every freakin' day I see questions regarding salt or hash.
And not a single one regarding password complexity. While
每一天我都会看到有关盐或哈希的问题。
而不是一个关于密码复杂性的问题。尽管
The only your concern should be password complexity.
您唯一关心的应该是密码的复杂性。
Why? Let me show you.
为什么?让我演示给你看。
extraordinary good salt + weak password = breakable in seconds
非凡的好盐 + 弱密码 = 秒破
It is always assumed that salt is known to attacker. So, by using some dictionary of most used passwords and adding [whatever extra-random-super-long] salt to them, a weak password can be discovered in seconds. Same goes for brute-forcing short passwords.
总是假设攻击者知道盐。因此,通过使用一些最常用密码的字典并向它们添加 [任何额外的随机超长] 盐,可以在几秒钟内发现弱密码。暴力破解短密码也是如此。
just sensible salt + strong password = unbreakable
只是明智的盐 + 强密码 = 牢不可破
Quite unique salt makes precomputed tables useless and good password makes both dictionary and brute-force attacks good for nothing.
非常独特的盐使预先计算的表无用,而好的密码使字典和暴力攻击都无济于事。
回答by Bruno Rohée
MD5 is not secure in itself because it is partially broken (collisions) and is too small of a digest anyway. If one doesn't want to use a proper password derivation function à la bcrypt, scrypt or PBKDF2you should at least use SHA-256 for new designs (and have a plan to migrate to SHA-3 when it will be out, so be sure to store the scheme you used to hash the password with the result, so both scheme can coexist as you use the new hashing procedure when people change passwords).
MD5 本身并不安全,因为它部分损坏(冲突)并且无论如何都太小了。如果您不想使用正确的密码派生函数,例如 bcrypt、scrypt 或PBKDF2,您至少应该将 SHA-256 用于新设计(并计划在它出来时迁移到 SHA-3,所以要一定要存储你用来散列密码的方案和结果,所以当人们更改密码时,当你使用新的散列程序时,这两种方案可以共存)。
If you intend to sell your program using MD5 in any capacity can be a show stopper for most government sales (e.g. in the US algorithms used must be FIPS 140-2 approved and many other countries got the same kind of requirements).
如果您打算以任何身份使用 MD5 销售您的程序,这可能会成为大多数政府销售的阻碍(例如,在美国,所使用的算法必须获得 FIPS 140-2 批准,而许多其他国家/地区也有相同的要求)。
回答by Mat
It doesn't do much against dictionary attacks, only twice as hard to compute a dictionary versus a single md5
, and md5
is pretty cheap these days.
它对字典攻击没有多大作用,计算字典的难度是单个 的两倍md5
,而且md5
现在非常便宜。
回答by technomage
The reason why random password salt is recommended for hashing password, so that an attacker who knows the password hash can't compare it to rainbow tableof pre-calculated hashed from dictionary.
之所以推荐使用随机密码salt对密码进行散列,这样知道密码散列的攻击者就无法将其与字典中预先计算的散列彩虹表进行比较。
If you're using password as salt, attacker can pre-calculate hashes of $word.md5($word) first from their dictionary
如果您使用密码作为盐,攻击者可以首先从他们的字典中预先计算 $word.md5($word) 的哈希值
回答by Decent Dabbler
With your solution you pretty much defeats the purpose of using a salt against precomputed dictionary attacks.
使用您的解决方案,您几乎无法使用盐来对抗预先计算的字典攻击。
With a precomputed dictionary, as the name implies, someone has already created a table of hashes (the computed md5
result) for particular words, ahead of time.
使用预先计算的字典,顾名思义,有人已经md5
提前为特定单词创建了一个哈希表(计算结果)。
Consider this table hashtable
(with imaginary hashes, just for illustration purposes)
考虑这个表hashtable
(带有虚构的哈希值,仅用于说明目的)
word | hash
------------
foo | 54a64
bar | 3dhc5
baz | efef3
Testing these values against your table, could be as simple as:
针对您的表测试这些值可能很简单:
SELECT h.word
FROM hashtable h, yourtable y
WHERE y.password = MD5( CONCAT( h.word, h.hash ) );
With a match, you'ld have the password.
通过匹配,您将拥有密码。
However, if you did NOT hash the password, before concatenating it again with the password and hashing it once more, it would be more difficult to attack it with a pre-computed dictionary. Because then the password would be for instance md5( 'testtest' )
which makes the precomputed table worthless, if the precomputed table has only taken into account single instances of the word.
但是,如果您没有对密码进行哈希处理,则在将其与密码再次连接并再次对其进行哈希处理之前,使用预先计算的字典对其进行攻击将更加困难。因为例如md5( 'testtest' )
,如果预计算表仅考虑单词的单个实例,那么密码将使得预计算表毫无价值。
You can easily see that it gets even more difficult if you did not use the password as a salt, but used another random string as salt. And it gets even more difficult still, when you create unique salts for every passwords. Of course, if you create unique salts per password, you'd have to save the salt in a separate column along with the passwords in a database row.
你可以很容易地看到,如果你不使用密码作为盐,而是使用另一个随机字符串作为盐,它会变得更加困难。当您为每个密码创建唯一的盐时,它变得更加困难。当然,如果您为每个密码创建唯一的盐,则必须将盐与数据库行中的密码一起保存在单独的列中。
So my advice would be:
所以我的建议是:
md5( 'uniquesalt' . 'password' );
Or actually, don't use md5
at all, but use the far better sha1
, sha256
(or higher) hashing algorithms.
或者实际上,不使用md5
所有,但使用好得多sha1
,sha256
(或更高版本),散列算法。