使用密码作为salt的md5哈希?

时间:2011-03-30 05:56:27

标签: php hash md5

md5($password.md5($password))

这对于密码哈希是否足够好?我并不是要求将此与bcrypt进行比较。

如果不安全,请告诉我原因。

6 个答案:

答案 0 :(得分:33)

为每个用户的密码使用不同的盐的原因是,攻击者无法获取所有散列密码的列​​表,并查看其中是否有任何符合“密码”或“12345”之类的哈希值的哈希值。如果您使用密码本身作为salt,则攻击者可以计算md5("12345".md5("12345"))并查看它是否与任何条目匹配。

据我了解,您可以在密码表上使用四种级别的哈希:

  1. - 将密码存储为纯文本。如果有人获得了您的数据库副本,他们可以访问所有帐户。纯文本很糟糕,'mkay?
  2. 哈希密码 - 存储密码的哈希值,并丢弃真实密码。如果有人获得了数据库的副本,他们就看不到任何密码,只能看到哈希值。 然而,如果任何用户使用了弱密码,那么他们的哈希值将出现在彩虹表中。例如,如果用户具有密码“password”,则存储在数据库中的md5哈希将是“5f4dcc3b5aa765d61d8327deb882cf99”。如果我在像the one at gromweb.com这样的彩虹表中查找该哈希值,它会吐出“密码”。
  3. 使用salt值 - 选择GUID之类的大型随机字符串并将其存储在配置文件中。在计算哈希值之前将该字符串附加到每个密码。现在彩虹表不太可能工作,因为它可能没有“password59fJepLkm6Gu5dDV”或“picard59fJepLkm6Gu5dDV”的条目。虽然预先计算的彩虹表不再有效,但如果攻击者知道您的盐值,您仍然可能会受到影响。攻击者可以计算弱密码加上盐的哈希,看看数据库中的任何用户是否使用了这个弱密码。如果你有几千个用户,那么每个哈希计算都可以让攻击者进行数千次比较。实际使用盐的方式可能取决于您使用的加密算法。为简单起见,只需将其想象为将salt和密码附加在一起即可。
  4. 使用不同的salt值 - 现在您可以使用与用户名,电子邮件地址甚至用户ID不同的内容,并将其与密码和配置中的大型随机字符串相结合在计算哈希值之前的文件。现在,知道你的盐的攻击者仍然需要重新计算每个用户的哈希值,看看他们是否使用了像“密码”这样的弱密码。
  5. 有关详细信息,请查看编码恐怖帖子“You're probably storing passwords incorrectly”。

答案 1 :(得分:4)

虽然对我来说似乎已经足够了,如果有人根据相同的算法预先计算了彩虹表,那么它将处于危险之中(很可能)。 因此,我宁愿使用电子邮件来获取盐,这似乎非常安全但可用。偏执狂可以添加一些恒定的全站点盐。

人们经常从密码盐(理论上)中做出太大的贡献,而在他们的应用程序中,他们允许使用简单的密码,并在实际中通过不安全的HTTP以纯文本形式传输它们。

每一天我都会看到有关盐或哈希的问题 而且没有一个关于密码复杂性的问题。而

唯一的问题应该是密码复杂性。

为什么呢?让我演示给你看。

非常好的盐+弱密码=在几秒钟内可破解

人们总是认为攻击者知道盐。因此,通过使用一些最常用密码的字典并向其添加[任意超级随机超长]盐,可以在几秒钟内发现弱密码。粗暴的短密码也是如此。

只是敏感盐+强密码=牢不可破

相当独特的盐使得预先计算的表毫无用处,而且良好的密码使得字典和暴力攻击都无济于事。

答案 2 :(得分:2)

它对字典攻击没有太大作用,计算字典的难度是单个md5的两倍,而md5现在相当便宜。

答案 3 :(得分:2)

MD5本身并不安全,因为它部分断裂(碰撞)并且无论如何都太小了。如果一个人不想使用正确的密码派生函数àlabcrypt,scrypt或PBKDF2你至少应该使用SHA-256进行新的设计(并计划迁移到SHA-3时) out,所以一定要存储你用来使用结果散列密码的方案,这样当人们更改密码时,当你使用新的哈希程序时,两个方案都可以共存。)

如果您打算以任何身份使用MD5销售您的程序,可以成为大多数政府销售的显示阻止(例如,在美国使用的算法必须通过FIPS 140-2认证,而许多其他国家/地区也有同样的要求)。

答案 4 :(得分:1)

建议使用随机密码盐进行散列密码的原因,以便知道密码哈希的攻击者无法将其与预先计算的字典散列的rainbow table进行比较。

如果您使用密码作为salt,攻击者可以先从字典中预先计算$ word.md5($ word)的哈希值

答案 5 :(得分:1)

使用您的解决方案,您几乎无法使用盐来预先计算字典攻击。

使用预先计算的字典,顾名思义,有人已经提前为特定单词创建了哈希表(计算出的md5结果)。

考虑这个表hashtable(带有假想的哈希值,仅用于说明目的)

word | hash
------------
foo  | 54a64
bar  | 3dhc5
baz  | efef3

针对您的表测试这些值可能非常简单:

SELECT h.word
FROM hashtable h, yourtable y
WHERE y.password = MD5( CONCAT( h.word, h.hash ) );

有了匹配,你就有了密码。

但是,如果您没有对密码进行哈希处理,在再次使用密码连接密码并再次对其进行哈希处理之前,使用预先计算的字典对其进行攻击会更加困难。因为密码将是例如md5( 'testtest' ),这使得预先计算的表毫无价值,如果预先计算的表只考虑了单词的单个实例。

如果您不使用密码作为salt,但是使用另一个随机字符串作为salt,您可以很容易地看到它变得更加困难。当你为每个密码创建独特的盐时,它仍然变得更加困难。当然,如果您为每个密码创建唯一的salt,则必须将salt与密码保存在一个单独的列中。

所以我的建议是:

md5( 'uniquesalt' . 'password' );

或者实际上,根本不要使用md5,而是使用更好的sha1sha256(或更高)哈希算法。