使用 SHA-512 和 salt 来散列 MD5 散列密码?
Posted
技术标签:
【中文标题】使用 SHA-512 和 salt 来散列 MD5 散列密码?【英文标题】:Use SHA-512 and salt to hash an MD5 hashed password? 【发布时间】:2012-04-19 04:12:59 【问题描述】:我正在使用一个使用 MD5(无盐)对用户密码进行哈希处理的系统。我想使用 SHA-512 和 salt 更安全地存储密码。
虽然这很容易为将来的密码实施,但我还想改进现有的 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。
非常正确。我实际上打算做关键拉伸,但在我的问题中没有说清楚。我最终使用了 PBKDF2,而不是天真地实现我自己的密钥拉伸算法。
【参考方案1】:
相信你的第二直觉。使用专门用于散列密码的现有库,而不是尝试自己编写。
可能使用 MD5 散列您的新密码,然后使用您的密码散列库对 MD5 进行散列。这样,您就可以保持与旧密码的向后兼容性。
即password_hash(所有旧的 md5 密码)和 password_hash(md5(新密码))
(警告:我不是密码学专家)
http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html
【讨论】:
哦,我不打算制作自己的哈希库,我只需要知道如何处理现有的 MD5 哈希密码! 我不是密码学专家,但我只是对现有的 MD5 密码运行密码散列函数。对于新密码,您将首先执行旧的 MD5 算法,然后将其提供给适当的密码散列函数。那,或者你可以以某种方式标记密码是使用数据库中的旧算法还是新算法(或者你存储它的任何地方)。 @tangrs 他的原始密码也是 MD5 散列的,它已经是安全的。他想用更安全的盐切换到 SHA-512。为什么你会向他建议双重哈希?那仍然不能解决如何区分新旧密码的问题。而双重哈希是通过默默无闻的安全,这和没有安全一样好,因为没有人知道到底发生了什么以及如何维护它。 我的意思是双重哈希作为向后兼容的一种方式。 (诚然,它确实看起来既便宜又懒惰)【参考方案2】:如果你先用 MD5 散列,你只会得到 MD5(128 位)的传播。 SHA512 的大部分空间不会被您的密码覆盖。所以你不利用SHA512,但不会比MD5差。
如果有人获得了 SHA512 哈希值并且不知道盐值(您必须以某种方式强制执行),您将获得的好处是无法查找哈希值并获得密码——这在 MD5 中是可能的您现在拥有的数据库。
所以是的,您可以重新散列现有的 MD5 密码。但正如第一段所述,将 MD5 应用于所有新密码然后将其哈希为 SH512 是一个坏主意。一个简单的实现是在数据库中的哈希值旁边有一个布尔值“salted”字段(但不要把盐放在那里)。
【讨论】:
but don't put the salt there
- 盐的全部意义在于它不必保密,只需将明文放在散列值旁边(每个密码都有一个唯一的散列!) .另外:“使用 SHA-512 散列 MD5 密码不会造成任何伤害”是基于任何实际事实还是只是一些直觉?因为通常按顺序应用多个哈希可能弊大于利..
散列函数的关键在于它提供了一个可变大小的字符串和 n 比特数之间的唯一映射。任何好的散列函数都可以避免冲突,实际上在 SHA-512 甚至 MD5 上都很难产生冲突(除非你有任意长度,而密码中没有)。将 128 位值映射到 512 位空间很简单(您有 2^(512-128) 个未使用的值)。碰撞(这是伤害)极不可能发生(概率 2^(128-512))。【参考方案3】:
具有加密原语的函数组合是危险的,如果可以避免,则不应这样做。针对您的问题类型的常见解决方案是在迁移期间保留两个哈希,在可能的情况下使用新哈希并透明地升级旧密码(当您检查密码并且匹配时,使用新算法重新哈希并存储它)
如果您有一个基于质询-响应的方案,您看不到明文密码,这将不起作用,但由于您似乎有一个不会更改的存储盐,我假设您的应用程序执行散列.
【讨论】:
这是一个很好的答案。我以前就实现过这种类型的解决方案,这是一个很好的方法。 感谢用户登录时透明重新散列的建议!您是否有任何链接可以解释为什么将 SHA-512 散列应用于 MD5 散列值不如将 SHA-512 散列应用于纯文本密码?我很想知道为什么... @JeremiahOrr:对于您的特定应用,正确使用足够长的不可预测的盐在安全性方面比更改散列方案做得更多。正如 j13r 所解释的,将 SHA 应用于 MD5 不会扩大可能的哈希空间,因为它们受到 MD5 可能结果的限制。此外,使用专门为密码优化的单向函数会更好,例如PBKDF2。 @JeremiahOrr:考虑一下这个夸张的例子。假设我定义了一个哈希函数,它将任何输入 m 映射为 0 或 1。正如您可能想象的那样,这不是一个密码安全的哈希函数,因为输出空间非常小。现在将 SHA-256 应用于此哈希函数的输出没有帮助(输出将是 SHA(0) 或 SHA(1)),因为 SHA-256 哈希的输出受第一个哈希的输出范围的限制功能。 @JaredNg 我非常怀疑密码是否比 MD5 哈希值多,即使考虑到地球上每个人使用的每个密码。【参考方案4】:如果您查看大多数银行和高安全性人员如何更改密码。他们中的大多数基本上要求使用旧加密方法的人创建新密码。我认为你的第一个解决方案是在所有现有的旧 MD5 密码用户上放置一个标志,并通知他们需要创建新密码并慢慢将他们迁移到新系统。这样,当您对系统进行故障排除时,如果出现任何问题,您就不会问这是新用户还是旧用户。我们是双重哈希还是单一哈希?永远不应该比较两个哈希作为可能的答案,因为如果 MD5('abc') => 123, SHA('NO') => 123,那意味着有人可能输入了错误的密码,但仍然可以进入。
【讨论】:
以上是关于使用 SHA-512 和 salt 来散列 MD5 散列密码?的主要内容,如果未能解决你的问题,请参考以下文章