使用SHA-512和盐值对MD5加密的密码进行加密?

9
我正在处理一个系统,它使用MD5(无盐)对用户密码进行散列。我想使用SHA-512和盐来更加安全地存储密码。
虽然这对于未来的密码很容易实现,但我也希望能够为现有的MD5散列密码进行改进,最好不需要强制所有用户更改密码。我的想法是仅仅使用SHA-512和适当的盐来对现有的MD5散列进行散列。我可以在数据库中设置某些标志,以指示哪些密码从明文进行了散列,哪些是从MD5散列进行散列的。或者在验证用户时尝试两种方法。甚至可以先用MD5对新密码进行散列,然后再进行SHA-512/salt散列,以便将其与旧密码相同对待。
从程序上看,我认为这不会成为问题,但我不了解加密/哈希的足够知识,无法判断通过SHA-512/salt散列将已经MD5散列的密码是否会影响其质量。我的第一反应是,如果有任何问题,结果会更加强大,相当于轻微的密钥拉伸。
我的第二个直觉是,我不确定自己在说什么,所以最好寻求建议。有什么想法吗?

SHA-512相对MD5提供的改进非常少(例如:MD5(salt + password)在实践中等同于SHA512(salt + password))。像MD5和SHA系列这样的通用哈希函数并不适用于存储密码。请使用bcrypt。 - NullUserException
非常正确。实际上,我打算进行密钥拉伸,但在我的问题中没有明确说明。最终,我使用了PBKDF2而不是天真地实现自己的密钥拉伸算法。 - Jeremiah Orr
4个回答

5
使用密码原语进行函数组合是危险的,如果可以避免则不应这样做。您的问题通常的解决方案是在迁移期间保留两个哈希值,在可能的情况下使用新哈希,并透明地升级旧密码(当您检查密码并且匹配时,请使用新算法重新哈希并存储它)。
如果您使用的是基于挑战-响应的方案,其中您无法看到明文密码,则此方法将无效。但是,由于您似乎具有不会更改的存储盐,因此我假设您的应用程序正在进行哈希处理。

这是一个很棒的答案。我之前实现过完全相同类型的解决方案,这是一个非常好的方法。 - user121356
感谢您对透明重新哈希化登录时的建议!您有没有任何链接可以解释为什么将SHA-512哈希应用于MD5哈希值比将SHA-512哈希应用于明文密码不安全?我很想知道为什么... - Jeremiah Orr
1
@JeremiahOrr:对于您的特定应用程序,使用足够长且不可预测的盐会在安全方面比更改哈希方案更有用。正如j13r所解释的那样,将SHA应用于MD5不会扩大可能哈希的空间,因为它们受到MD5可能结果的限制。此外,使用专门针对密码进行优化的单向函数会更好,例如[PBKDF2](http://en.wikipedia.org/wiki/PBKDF2)。 - mensi
2
@JeremiahOrr:考虑这个夸张的例子。假设我定义了一个哈希函数,将任何输入m映射到0或1。正如你所想象的那样,这不是一个密码学安全的哈希函数,因为输出空间太小了。现在对这个哈希函数的输出应用SHA-256也没有帮助(输出将是SHA(0)或SHA(1)),因为SHA-256哈希的输出受第一个哈希函数的输出范围限制。 - Jared Ng
@JaredNg 我非常怀疑密码的数量比 MD5 哈希值还要多,即使考虑到地球上每个人使用的每个密码。 - NullUserException
@NullUserException 在很大程度上,您是正确的,但示例的重点在于演示哈希散列函数输出的哈希值并不会增加安全性。 - Jared Ng

4
如果你先使用MD5进行哈希,那么你只能得到MD5的散列(128位)。SHA512空间的大部分将不被你的密码覆盖。因此,你没有利用SHA512的优势,但它不会比MD5更糟糕。
你有一个好处,如果有人获取SHA512哈希值却不知道salt(你必须以某种方式强制执行),就无法查找哈希值并获取密码 - 这是使用现有的MD5数据库可能会出现的问题。
所以,是的,你可以重新对现有的MD5密码进行哈希。但正如第一段所解释的那样,将MD5应用于所有新密码,然后再将其哈希为SH512是一个坏主意。一个简单的实现方法是在哈希值旁边的数据库中添加一个布尔类型的'salted'字段(但不要把salt放在那里)。

“但不要把盐放在那里” - 盐的整个意义在于它不必保密,可以直接放在散列值旁边(每个密码都有一个唯一的哈希值!)。另外:将MD5密码哈希化为SHA-512不会造成任何伤害这种说法是基于实际事实还是凭直觉?因为通常情况下,连续应用多个哈希可能会弊大于利。 - Voo
哈希函数的作用在于它提供了一个将可变长度字符串和 n 位数字之间进行唯一映射的方法。任何好的哈希函数都会避免碰撞,事实上,在 SHA-512 和甚至 MD5 中很难产生碰撞(除非你具有任意长度,而密码通常不会有那么长)。将一个128位的值映射到512位的空间中非常容易做到(你有2^(512-128)个未使用的值)。碰撞(造成的危害)极不可能发生(概率为 2^(128-512))。 - j13r

1

相信你的第二直觉。使用专门用于哈希密码的现有库,而不是试图自己编写。

可能会使用MD5对新密码进行哈希,然后使用密码哈希库对MD5进行哈希。这样,您可以与旧密码保持向后兼容性。

即 password_hash(所有旧的,经过md5处理的密码) 和 password_hash(md5(新密码))

(警告:我不是密码学专家)

http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html


哦,我不打算自己编写哈希库,我只需要知道如何处理现有的MD5哈希密码! - Jeremiah Orr
我不是密码学专家,但我会对现有的MD5密码运行一个密码哈希函数。对于新密码,您应该先使用旧的MD5算法,然后将其输入正确的密码哈希函数中。或者,您可以在数据库(或存储位置)中标记密码是否正在使用旧的或新的算法。 - tangrs
@tangrs 他的原始密码已经使用了 MD5 哈希,已经很安全了。他想要更换为使用盐值的 SHA-512 哈希,这更加安全。为什么你会建议他使用双重哈希呢?这样做仍然无法解决如何区分新密码和旧密码的问题。而且双重哈希是通过混淆来实现安全性,这和没有安全措施一样不好,因为没有人知道到底发生了什么和如何维护它。 - Churk
我之前提到双重哈希作为向后兼容的一种方式。(诚然,这似乎有些便宜和懒惰) - tangrs

0

如果你看看大多数银行和高安全性人员如何更改密码,他们基本上会要求使用旧加密方法的人创建新密码。我认为你的第一个解决方案是在所有现有的旧MD5密码用户上放置一个标志,并通知他们需要创建新密码,并慢慢将他们迁移到新系统。这样,当你排除系统故障时,如果出了问题,你不会问这是一个新用户还是一个旧用户。我们是否双重哈希或单一哈希?永远不应该将两个哈希值进行比较,因为如果MD5('abc')=> 123,SHA('NO')=> 123,那么这意味着有人可能输入了错误的密码但仍然可以登录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接