恐怕我会因为问这个老问题而被人扔西红柿,但是就这样吧。
在阅读了一遍又一遍地从现有的散列函数中编写自己的密码散列是危险的之后,我仍然不明白其中的逻辑。这里有些例子:
md5(md5(salt) + bcrypt(password))
scrypt(bcrypt(password + salt))
sha1(md5(scrypt(password + md5(salt))))
反对这些的典型论据如下:
你不是密码学家!您不知道这些哈希是否更安全。把它留给知道他们在做什么的专家。这些不会增加额外的安全性。
诚然,他们没有将函数改进为哈希(即,使其更难逆转或发现冲突等),但他们肯定不会让哈希变得更糟吗?如果他们这样做了,那么黑客将能够在他们认为合适的情况下将标准散列密码重新散列到这些古怪的散列中并削弱散列?我不买。
第二个论点:
Kerckoffs 原则:即使系统的一切都已知,密码系统也应该是安全的。
同意。这基本上是首先不将密码存储为明文的动机。但是,如果我对第一个批评的回应成立,那么这些古怪的散列仍然可以作为安全散列,并且我们的系统不会像使用标准散列那样违反 Kerckoffs 的原则。
以下是使用“古怪”散列而不是普通散列的两个可能(据我所知,这是值得的)优势:
- 当然,如果攻击者拥有源代码,您的系统应该是安全的,但很有可能您的攻击者无法访问您的源代码,并且可能无法猜测您古怪的哈希值,从而进行任何暴力尝试强行不可能。
- (这是我提出这个问题的真正动机)
BCrypt
被认为是安全的,对 CPU 和 GPU 来说很难(很棒),但使用专用硬件可以非常快。SCrypt
据说很难在 CPU、GPU 和当前可用的专用硬件上进行暴力破解,但由于缺乏曝光度,它是较新的并且不像 BCrypt 那样受到加密社区的信任。但是哈希不是BCrypt(SCrypt(password + salt))
两全其美吗?
我很欣赏大多数对这些自制散列的咆哮背后的激情/愤怒来自普通程序员对什么是好的散列缺乏了解,并且担心鼓励这种古怪的散列将不可避免地以弱和无用而告终哈希进入生产代码。但是,如果古怪的哈希是由可靠且受信任的哈希精心构建的,那么安全性的收益难道不是非常有价值和真实的吗?
更新
我得到了一堆很好的答案,谢谢。我的假设似乎忽略了一点,虽然组合哈希不能更容易破解原始密码并因此破解组成哈希,但两个或多个安全哈希的组合可以 - 至少在原则上 - 更弱由于它们之间未经研究且复杂的交互,因此比其任何一个内部哈希值都要高。这意味着可以找到一些通过古怪散列的字符串,而不必破坏组成它的散列。