BCrypt是在C#中使用的良好哈希算法吗?在哪里可以找到它?[关闭]


129

我读过,在散列密码时,许多程序员建议使用BCrypt算法。

我正在用C#编程,想知道是否有人知道BCrypt的良好实现?我找到了此页面,但我真的不知道它是否是伪造的。

选择密码哈希方案时应注意什么?BCrypt是“良好”的实现吗?

Answers:


148

首先,一些重要的术语:

散列 -采取字符串并产生一系列不能还原为原始字符串的字符的行为。

对称加密 -(通常简称为“加密”)-采取一个字符串并产生一系列字符的动作,这些字符序列可以 通过使用对其进行加密的相同加密密钥来解密为原始字符串。

彩虹表 -查找表,其中包含在特定哈希算法中哈希的所有字符变体。

-在散列之前附加到原始字符串的已知随机字符串。

对于.NET Framework,Bcrypt尚没有经过验证的参考实现。这很重要,因为无法知道现有实现中是否存在严重缺陷。您可以在此处获得BCrypt for .NET的实现。我对密码学还不够了解,很难说它是一个好实现。密码学是一个非常深的领域。 不要尝试构建自己的加密算法。说真的

如果要实现自己的密码安全性(叹气),那么您需要做几件事:

  1. 使用相对安全的哈希算法
  2. 在对每个密码进行哈希处理之前先对其加盐。
  3. 为每个密码使用唯一且较长的盐,然后将盐与密码一起存储。
  4. 需要强密码

不幸的是,即使您做了所有这些事情,一个坚定的黑客仍然可以潜在地找出密码,这只会花很长时间。那是您的主要敌人:时间

bcrypt算法的工作,因为它需要5个数量级更长的时间来散比MD5密码 ; (并且仍然比AES或SHA-512长得多)。它迫使黑客花费更多的时间来创建彩虹表来查找您的密码,从而大大减少了密码被黑客入侵的可能性。

如果您正在对密码加盐和散列,并且每种盐都不同,那么潜在的黑客将不得不为salt的每种变体创建一个彩虹表,只为一个盐+哈希密码创建一个彩虹表。这意味着,如果您有100万用户,那么黑客必须生成100万个彩虹表。如果您为每个用户使用相同的盐,那么黑客只需生成1个彩虹表即可成功入侵您的系统。

如果您不给密码加盐,那么攻击者所需要做的就是为其中的每种实现(AES,SHA-512,MD5)提取一个现有的Rainbow表,然后看看是否与哈希匹配。这已经完成,攻击者无需自己计算这些Rainbow表

即使有所有这些,您也必须使用良好的安全做法。如果他们可以在您的站点上成功使用其他攻击媒介(XSS,SQL Injection,CSRF ),则良好的密码安全性无关紧要。这听起来像是一个有争议的声明,但请考虑一下:如果我可以通过SQL注入攻击获取所有用户信息,或者可以让您的用户通过XSS给我他们的cookie,那么您的密码有多好都没关系安全是

其他资源:

  1. 杰夫·阿特伍德(Jeff Atwood):简化了.NET加密(非常适合哈希概述)
  2. 杰夫·阿特伍德:我刚刚以您的身份登录
  3. 杰夫·阿特伍德(Jeff Atwood):您可能存储了错误的密码
  4. 杰夫·阿特伍德(Jeff Atwood):速度哈希

注意:请推荐其他好的资源。我一定已经阅读了数十位作者的十几篇文章,但很少有文章像Jeff一样清楚地写过。找到后,请在文章中进行编辑。


也许在您的盐段中添加了必须随机选择盐的位置
Jacco

2
@Jacco好电话,已添加。虽然那并不重要。您可以只使用盐的登录时间戳。其区别在于,攻击者随后需要针对每种盐重新计算彩虹表。这就是让它变得困难的原因,而不是它是随机选择的。将其随机化会增加另一层混淆,但是一旦攻击者能够看到您的数据库,这将毫无用处(这是首先导致我们所有心痛的问题)。
乔治·斯托克

3
不是真的,盐不必是秘密的,只是每个实例都是唯一的。由于不可能(在全球范围内)是唯一的,因此随机选择是次之。另外,由于熵不足,因此时间戳也不是一个好选择
Jacco

7
对于您的陈述“如果他们可以成功使用XSS或SQL注入,那么良好的密码安全性就无关紧要了”。相反,如果他们能够成功地XSS或SQL注入您的站点,那么良好的密码安全性就显得尤为重要。这里的关键是“纵深防御”-您应在应用程序的每一层上尽可能地加强安全性。
jammycakes 2011年

2
@jammycakes绝对;我的观点丢了:您不能只说:“嘿,我们对密码进行哈希处理和加盐处理,“我们还可以”!
乔治·斯托克2014年

74

不得在.NET中使用 BCrypt。您必须像使用内置.NET Framework实现一样使用 PBKDF2。它是.NET中唯一免费提供的经过密码验证的实现,并且是NIST推荐算法

由于这个原因,StackId以前使用BCrypt并移至PBKDF2:

对于那些好奇的人,我们使用PBKDF2对密码进行哈希处理。 通过几层间接访问,相关代码在这里( http://code.google.com/p/stackid/source/browse/OpenIdProvider/Current.cs#1135)。在较早的迭代中,我们使用BCrypt。但由于它已内置到.NET框架中而移至PBKDF2,而BCrypt则要求我们验证实现(不小的工作)。

凯文·蒙特罗斯(Kevin Montrose),2011年5月27日

(GitHub上的更新链接)

编辑:用密码术语进行验证的含义似乎不容易理解,经过验证的实现意味着已被加密证明没有错误地实现。这样做的成本很容易达到20,000美元或更高。我在进行OpenSSL研究时回想起了这一点,并读到他们表示尚未完成整个验证过程的地方,但是如果您需要充分验证他们可以为您指出正确的道路,并提到相关的费用。某些政府要求包括对经过验证的加密算法的强制要求。

.NET中的bcrypt实现尚未经过验证。使用未经验证的加密实现,您不能绝对确定其中没有故意的恶意错误,例如允许后门进入加密的内容,或者是由于意外的实现错误而导致的密码不安全的数据。

2014编辑:对于任何质疑使用经过验证的密码算法的必要性的人,请看一下OpenSSL中令人发指的骇客所造成的破坏。那就是使用未经验证的实现的成本。它是安全的...。直到您发现任何人都可以读取服务器的整个内存内容为止。

引入Heartbleed的更改的作者Robin Seggelmann表示,他“错过了验证包含长度的变量”,并否认有意提交有缺陷的实现。在Heartbleed公开之后,Seggelmann建议着重于第二个方面,指出OpenSSL没有得到足够多的人的审查。

这是未经验证的实现的定义。即使是最小的缺陷也可能导致整个安全性受损。

2015编辑:删除了基于推荐的语言,并替换为绝对语言。内嵌原始凯文·蒙特罗斯(Kevin Montrose)的后人评论。


25
引用链接的注释:“ [我们已移至PBKDF2,因为它内置于.NET框架中,而BCrypt则要求我们验证实现”。请注意,该注释并没有说明算法更好,只是SE Dev Team认为内置PBKDF2 实现比外部库(最终是判断调用)更受信任。
Piskvor在2011年

3
@Piskvor我更新了答案。这不是SO团队认为安全的问题,而是关于固有证明的安全或希望安全之间的判断。后者在密码学方面是不可接受的。
克里斯·马里西奇

6
我不知道如何将所有bcrypt哈希密码迁移到新的哈希值?他们是否需要原始密码来使用新算法对其进行哈希处理?
Dharmendar Kumar'DK'2014年

8
@DK我什至认为您不必要求他们重设密码。我相信,下次登录时(他们将提供纯文本密码)即可。
马特·科卡伊

12
这是一个糟糕的建议,令我惊讶的是它有这么多赞成票。与用C验证整个SSL实现类似,用托管语言验证BCrypt实现要简单得多。Heartbleed完全不相关。您最好提一下类似哈希类型检查的PHP类型强制问题。另外,虽然PBKDF2实际上非常适合,但它是KDF,而不是密码哈希算法,而BCrypt更适合。无论如何,无论如何,如今无论如何使用Argon2还是有意义的,为此,它有一个经过良好测试的C#库
Polynomial
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.