我正在研究哈希算法,但找不到答案。
- Bcrypt使用河豚
- 河豚比MD5好
- 问:但是河豚比沙512好吗?
谢谢。。
更新:
我想澄清一下,我理解散列和加密之间的区别。促使我这样问这个问题的是本文,作者将bcrypt称为"自适应散列"
因为bcrypt是基于河豚的,所以我认为河豚是一种哈希算法。如果答案指出它是加密的,那么在我看来,它不应该在本文中占有一席之地。更糟糕的是,他得出的结论是BCRYPT是最好的。现在让我困惑的是phpass类(我认为用于密码散列)使用bcrypt(即blowfish,即encryption)。根据你们告诉我的新信息(河豚是加密的),这个类听起来是错误的。我错过什么了吗?
- 这并不是错的;请参阅我的答案更新,了解bcrypt如何工作以及为什么它与基于哈希的"单向"算法具有相同的用途。
- 默认情况下,bcrypt的"工作系数"更高。假设sha不……除非您使用passhash9,它可以与工作因子一起使用。为什么这个问题被解决了?这离答案还很远,但很重要。
- 相关链接已断开…………
它应该足以说明bcrypt或sha-512(在类似pbkdf2的适当算法的上下文中)是否足够好。答案是肯定的,这两种算法都足够安全,通过实现缺陷(而不是密码分析)会发生破坏。好的。
如果你坚持要知道哪个更好,sha-512已经得到了NIST和其他机构的深入审查。这很好,但缺陷已经被认识到,虽然现在不可开发,但导致了对新哈希算法的SHA-3竞争。另外,请记住,哈希算法的研究比密码算法的研究"新",而且密码学家仍在学习它们。好的。
尽管Bcrypt作为一个整体没有像河豚本身那样受到严格的审查,但我相信,基于一个具有良好理解结构的密码,可以给它一些基于哈希的认证所缺乏的固有安全性。此外,使用通用GPU作为攻击基于SHA-2–的哈希的工具更容易,因为它的内存需求,优化BCRYPT需要更专业的硬件,如带一些板载RAM的FPGA。好的。
注:bcrypt是一种在内部使用河豚的算法。它本身不是加密算法。它用于不可逆转地隐藏密码,就像哈希函数用于执行"单向哈希"一样。好的。
密码哈希算法被设计为不可能反转。换句话说,如果只给出哈希函数的输出,则需要"永远"才能找到将产生相同哈希输出的消息。事实上,找到任何两个产生相同哈希值的消息在计算上是不可行的。与密码不同,哈希函数不是用键参数化的;相同的输入总是产生相同的输出。好的。
如果有人提供的密码散列到密码表中存储的值,则会对其进行身份验证。特别是,由于哈希函数的不可逆性,假设用户不是一个获得哈希并将其颠倒以找到工作密码的攻击者。好的。
现在考虑Bcrypt。它使用Blowfish加密一个魔术字符串,使用一个从密码"派生"的密钥。稍后,当用户输入密码时,将再次派生密钥,如果用该密钥加密产生的密文与存储的密文匹配,则对用户进行身份验证。密文存储在"password"表中,但派生密钥从不存储。好的。
为了破解这里的密码,攻击者必须从密文中恢复密钥。这称为"已知明文"攻击,因为攻击知道已加密的魔法字符串,但不知道使用的密钥。人们对河豚进行了广泛的研究,目前还没有已知的攻击可以让攻击者通过一个已知的明文找到密钥。好的。
所以,就像基于不可逆算法的密码摘要一样,bcrypt通过密码、salt和成本因素生成不可逆的输出。它的优势在于河豚对已知明文攻击的抵抗力,这类似于对摘要算法的"第一次图像前攻击"。因为它可以用来代替哈希算法来保护密码,所以bcrypt被混淆地称为"哈希"算法本身。好的。
假设彩虹表被盐的正确使用所阻碍,任何真正不可逆的功能都会减少攻击者的尝试和错误。攻击者进行测试的速度取决于不可逆"散列"算法的速度。如果使用哈希函数的单次迭代,攻击者可以使用1000美元左右的设备每秒进行数百万次测试,在几个月内测试所有长达8个字符的密码。好的。
但是,如果摘要输出被"反馈"数千次,那么在该硬件上测试同一组密码将需要数百年的时间。Bcrypt通过在其密钥派生例程中迭代来实现相同的"密钥强化"效果,而适当的基于散列的方法(如pbkdf2)也可以实现相同的效果;在这方面,这两种方法是相似的。好的。
因此,我对bcrypt的建议源于以下假设:1)河豚具有与sha-2散列函数家族相似的详细程度;2)密码的密码学分析方法比散列函数的密码学分析方法开发得更好。好的。好啊。
- 感谢您的回答和评论。我确实是在询问密码分析原因/彩虹表等,但我也觉得Blowfish是在散列,而不是像phpass类(我相信是用于密码散列的类)中使用的加密。我已经相应地更新了我原来的帖子。
- 非常好的更新。谢谢。
- +1个很棒的职位。但我有两个问题。十多年前,河豚被twofish所取代,难道一个系统不应该利用现代原始生物吗?此外,在诸如Web应用程序这样的系统中,数千次迭代似乎是浪费的,在这些系统中,许多人随时都在登录。例如,pbkdf2仅在一次有一个人登录的情况下实现,例如加密文件系统的string2key函数。我用一句谚语"如果攻击者举得太重,那么对你的服务器来说就太重了。"你怎么看?
- 我认为使用更现代的原始语言没有什么问题。随着时间的推移,人们经常会发现漏洞,而twofish是利用从河豚身上获得的知识开发出来的。然而,我不知道哪些特定的弱点会使使用河豚无效,所以也可以提出一个"如果没有破坏"的论点。你关于攻击者的格言听上去不太好。即使您选择的算法需要数年时间才能让攻击者测试10亿个密码,它在合法应用程序中的时间消耗也微乎其微。
- @Erickson下面这句话很容易让人误解:"与密码不同,哈希函数不是用键参数化的;相同的输入总是产生相同的输出。"虽然salt不是键,但salt的关键是使用不同的salt会导致相同的字符串哈希到不同的值。
- 如果您查看任何哈希函数的规范,您将看不到任何关于"salt"的内容。唯一的参数是要消化的消息。查看任何密码的规范,您将看到函数是用键参数化的。可以(或者不可以)与哈希一起使用的"salt"只是消息的一部分。哈希算法不需要它,也不专门处理它,并且无法将其与消息的其余部分区分开来。因此,虽然消息经常通过salt更改是正确的,但是给定的消息只产生一个哈希。
- @Rook为什么要说"PBKdf2只在一次有一个人登录的场景中实现,比如加密文件系统的String2Key函数。"?
- @埃里克森布莱克怎么样?这提到盐好几次。
- @Rook关于"数千次迭代"的评论似乎很浪费,使用这些算法(bcrypt或pbkdf2/sha-512)生成哈希的高成本使它们成为密码哈希的理想选择。正如埃里克森所回答的,这是一个可以接受的服务器成本;一个必要的邪恶。了解这可能会打开DoS攻击向量。攻击者可以用足够的登录尝试淹没服务器,从而锁定合法用户。限制登录尝试有助于缓解这种情况,但是您有一个不同的DOS向量,在该向量中特定的用户可能被锁定。安全很难。
- @作为一个Pentester,我报告了锁定帐户的应用程序,并且报告了不防止暴力的应用程序。理想情况下,一个有问题的IP地址必须解决一个验证码,另外,如果一个用户名是目标(即使该用户名不存在),那么该帐户应该在验证之前解决一个验证码。执行每分钟x的速率限制也是可以接受的。相关:security.stackexchange.com/questions/25444/…
- @Rook:虽然Ratelimiting应用程序是一个很好的实践,但在这种情况下,您可能会假设数据库已下载并放置在没有您描述的速率限制的设备上。
- @Ellert van Koperen我关心的是应用程序拒绝服务,这是pbkdf2的一个严重问题,因为它没有最大字符串长度。
- @我不清楚你在说什么。您是否担心在使用pbkdf2身份验证的应用程序上尝试非常长的密码时所花费的CPU时间?我不认为时间与密码长度之间的比例与迭代次数之间的比例非常快。在任何情况下,应用程序都可以施加最大密码长度限制,就像它应该施加最小长度和其他选择条件一样。如果这不是你的意思,请澄清。
- @埃里克森,我认为你混淆了已知的明文。"已知明文攻击"是攻击者知道未加密消息的地方。但是,未加密的消息(在本例中是密码)是未知的;它是攻击的对象。
- @Samueljaeschke不,我所指的纯文本是:"orpeanbeholderscrydoubt"。它是BCRYPT规范的一部分。要恢复密码,攻击者必须找到用于加密"orpeanbeholderscrydoubt"的密钥,以生成存储的哈希。然后,他们必须找到可以从中派生该密钥的密码。
我同意埃里克森的回答,但有一点需要注意:出于密码认证的目的,bcrypt比sha-512的单次迭代要好得多——这仅仅是因为它慢得多。如果你不明白为什么在这个特定的游戏中慢是一个优势,再次阅读你链接到的文章(向下滚动到"速度正是你不想要的密码散列函数。")。
当然,您可以通过对sha-512进行数千次迭代来构建一个安全的密码散列算法,就像phk的md5算法一样。ulrich drepper为glibc的crypt()做了这个。但是,如果您已经有了一个经过测试的BCrypt实现,那么这样做没有特别的原因。
- 希望我的答案能够清楚地表明,单个哈希迭代是不够的(遗憾的是,即使是这种基本的知识水平也无法假定)。如果使用哈希函数的单次迭代,攻击者可以使用1000美元左右的设备每秒进行数百万次测试,在几个月内测试所有长达8个字符的密码。但是,如果摘要输出被"反馈"数千次,那么在该硬件上测试相同的密码集将需要数百年的时间。Bcrypt通过迭代实现了相同的"密钥强化"效果…"
- @埃里克森:是的,虽然我想你可能把莱德埋在那里了。我试图指出的一点是,直接比较bcrypt和sha-512并不真正相关,因为一个是密钥派生函数,另一个只是密码原语,不适合单独使用。
- codahale.com/how-to-safety-store-a-密码
- 使用数千轮的sha-512并非闻所未闻,而且考虑到它包含在各种crypt实现中(包括我使用的PHP中),当我读到最初的问题时,我甚至假设当他问起sha-512时,op的意思是-他实际上指的是数千轮的sha-512与bcrypt,后者使用的是100s或数千次迭代本身。
河豚不是散列算法。这是一种加密算法。这意味着可以使用Blowfish加密某些内容,然后稍后可以将其解密回纯文本。
sha512是一种哈希算法。这意味着(理论上)一旦散列了输入,就不能再得到原始输入。
它们是两种不同的东西,设计用于不同的任务。对于"河豚比sha512好吗?",没有"正确"的答案。你不妨问"苹果比袋鼠好吗?"
如果您想了解更多有关此主题的信息,请访问以下链接:
- 我认为问题是使用bcrypt作为对密码的不可逆保护,就像哈希用于此目的一样。
- @埃里克森的文字"问:但是河豚比沙512好吗?"在我看来很清楚,这表明OP不理解这两种算法之间的区别。
- 这里是OP。事实上,基于Glen的Asnewer,Blowfish是一种加密算法(我理解这与哈希算法不同),我现在意识到我的问题"是"是混淆了的。但现在令人困惑的是,phpass类(我认为用于密码散列)使用bcrypt(即blowfish,即encryption)。如果河豚是加密的,为什么phpass会使用它来散列密码,对我来说这似乎是一个缺陷,不是吗?我错过什么了吗?
- 然而,问题是,哪些苹果和袋鼠更适合特定的任务。河豚是一个比sha更好的散列函数,因为它需要散列的时间。我看到的大多数sha实现都非常快。您需要一个缓慢的密码散列算法。
- 这个答案是正确的,因为Blowfish是一种加密算法,但在这种情况下(例如,在bcrypt中使用时),它通过从源字符串中派生一个密钥并使用该密钥加密一个幻数,被用作散列算法。这使得它不可逆,本质上是一个散列函数。即使知道明文和加密数据,也无法从密码计算密钥。
- 在操作速度方面,当您使用sha-512进行密码散列时,您希望使用数千轮,而不是一轮。
- @托马斯鲁特为什么不呢?我不是完全跟着你。我对你所说的理解是,它从一个字符串中派生出一个密钥,并使用它来加密一个幻数(它从哪里得到的??),但即使您有相同的起始字符串,也不能再次到达相同的键….?什么?我知道我是误解,因为这毫无意义——如果给定相同的密码,你不能到达相同的散列值,显然bcrypt不会有用。
- 通常,要用Blowfish加密某些内容,首先要加密一条消息和一个要加密的特殊密钥,最终结果是只能由生成该密钥的人解密的加密消息。如果你知道原始信息,你就不能用它来找出钥匙是什么。因此,当它被用作临时散列算法时,您可以使用希望散列的字符串作为密钥,并且只使用"幻数"(一个公开的字符串)作为要加密的消息。这样,就没有办法回到您散列的字符串。
- 这就是如何将加密算法转换为单向散列。假设"message"始终是常量,它是一个众所周知的字符串,相同的加密密钥将始终导致相同的加密消息,但您不能反转它以取回加密密钥。
河豚并不比MD5或SHA512更好,因为它们有不同的用途。MD5和SHA512是哈希算法,Blowfish是一种加密算法。两个完全不同的密码函数。
我刚发现这个:
http://codahale.com/how-to-safety-store-a-密码/
这篇文章的作者可能是错的吗?
- 这并不是说他错了,只是他忽略了大量关于如何应用散列算法的文献,即。它们应该在键派生函数中迭代使用,就像bcrypt那样。
我建议使用ulrich drepper的基于sha-256/sha-512的crypt实现。
我们将这些算法移植到Java,您可以在FTP://FTP.ARLUT.UTXA.EDU/JavaAHASH/中找到它们的免费授权版本。
请注意,大多数现代(L)unice在它们的/etc/shadow文件中都支持drepper的算法。
- pwdtk sourceforge.net/projects/pwdknet使用hmac-sha512,但是它在许多迭代中创建了"slowness",也就是像这里其他人所说的键拉伸。如前所述,bcrypt比单个sha-512更好,但是如果您在pbkdf2之类的东西中使用sha-512,那么您就很安全(只要您使用大型的加密随机salt和足够的迭代来强制时间生成彩虹表),我刚刚发布的api是由我构建的,并且将在.net中执行您想要的操作(如果您是这样的话)。为(未来读者的利益)开发