在 C# ASP.NET 中添加自定义 hashAlgorithmType
我有一个页面需要加强安全性。我正在使用内置的 MembershipProvider 功能,并且当前将 hashAlgorithmType
设置为 SHA512。我有 BCrypt.NET 库(http://bcrypt.codeplex.com/),当我从代码中调用它的函数时,它似乎工作得很好,但我在弄清楚如何创建适当的函数时遇到了最糟糕的时间Web.config 中的
部分让我创建一个 hashAlgorithmType
。
我在网上找到了以下代码片段:
<mscorlib>
<cryptographySettings>
<cryptoNameMapping>
<cryptoClasses>
<cryptoClass MyHash="MyHashClass, MyAssembly
Culture=neutral, PublicKeyToken=a5d015c7d5a0b012,
Version=1.0.0.0"/>
<cryptoClass MyCrypto="MyCryptoClass, MyAssembly
Culture=neutral, PublicKeyToken=a5d015c7d5a0b012,
Version=1.0.0.0"/>
</cryptoClasses>
<nameEntry name="System.Security.Cryptography.HashAlgorithm"
class="MyHash"/>
</cryptoNameMapping>
<oidMap>
<oidEntry OID="1.3.36.3.2.1" name="MyCryptoClass"/>
</oidMap>
</cryptographySettings>
</mscorlib>
如果你愿意,可以叫我菜鸟,但我显然不具备了解这一点所需的知识。我所需要的只是一种方法来告诉会员提供者类似
对应于类似 string hashed = BCrypt.HashPassword(password, BCrypt.GenerateSalt( 12));
进行加密,bool matches = BCrypt.CheckPassword(candidate, hashed);
进行解密。请告诉我有一个简单的答案。如果需要的话,我可以从头开始重写登录系统,但我已经有了一个工作实现,我真的很想更改其哈希算法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我相信配置模式必须应用于 machine.config 文件;如果您需要能够轻松地推出此代码,这不一定是一个伟大的举动。
您可以通过 CryptoConfig 类通过调用 AddAlgorithm 的名称可以以后使用。
只要 BCrypt 哈希提供程序实现了
HashAlgorithn
,您就应该能够简单地注册它,您也可以通过使用您使用的名称调用HashAlgorithm.Create(string)
来测试它验证它是否正确构建了算法。然后,会员提供商应该能够毫无问题地使用它。
这是一篇关于此主题的好文章。
更新
(深呼吸)-抱歉,如果这是 tl;博士。
好的,在阅读了 BCrypt.Net 的密码哈希后,它显然很好,并且遵循公认的做法。它也与
HashAlgorithm
类的工作方式完全不兼容,因为它需要额外的状态才能发挥其魔力,并且不能简单地扩展以实现HashAlgorithm
合同。因此,您有一个选择 - 坚持使用
MembershipProvider
并使用 SHA512,就像您已经在做的那样 - 您正在谈论加强页面上的安全性,所以我想在那里可能是身份验证本身的问题,而不是密码的存储问题(当然,仍然必须正确完成) - 因此请考虑简单地确保身份验证流量是通过 HTTPS 发送的(如果尚未通过 HTTPS 发送)。盲目使用密码拉伸算法有其自身的问题 - 请参阅对 我自己的回复最近关于此主题的 SO - 如果您在服务器上进行拉伸,您可能最终会导致网站受到 DOS 攻击!
正如您所建议的,另一种选择是完全由您自己管理会员资格 - 因此您可以使用您想要的任何类型并手动管理密码信息的必要存储。
我的网站现在使用一种与 PBKDF2 非常相似的算法,该算法是我从 Bruce Schneier 和 Niels Ferguson 的书《实用密码学》中借鉴的,为此我使用 512 位随机盐和 SHA512(存储很便宜)加上数千次迭代来散列明文。服务器对每个应用程序域进行一次基准测试,以建立相当于毫秒范围的保护“级别” - 因此,随着时间的推移,即使硬件有所改进,新散列的密码也将获得恒定的保护级别。该库也是独立的,如果我们必须在 SQL 级别生成密码记录,我可以将其部署到 SQL Server 2008 R2 以提供 CLR SP。
但这只能保护密码——然后您需要一个可以保护登录行为的身份验证机制;加上另一个用于保护经过身份验证的会话令牌的系统(.Net 的身份验证 Cookie 系统实际上对此非常有用)。
在此之后,我现在花了一周的时间来实现我当时拥有的 SCRAM 原语插入我的 MVC Web 服务进行身份验证,我计划执行相同的操作以启用使用 Javascript 从 Web 浏览器登录(锁定非 JS 客户端)。客户端的关键是进行所有的哈希计算;因此我坚持使用 SHA,因为成熟的实现几乎可以在任何环境中使用(例如,我们也有 iPhone 应用程序 - 并且它们也需要进行身份验证)。
然而,就您而言,根据对 MembershipProvider 的现有投资,我认为 512 位 SHA 加 SSL 加 Asp.Net 的身份验证 cookie 就足够了 - 只要数据库确实 secure(!) 并且站点中没有 SQL 注入漏洞。
I believe that config pattern must be applied to the machine.config file; which isn't necessarily a great move if you need to be able to roll out this code easily.
You can programmatically register the BCrypt encryption primitive(s) with the CryptoConfig class through a call to AddAlgorithm with a name that can you can later use.
So long as the BCrypt hash provider implements
HashAlgorithn
you should be able to register it simply, you can also test this by callingHashAlgorithm.Create(string)
with the name you use to verify that it builds the algorithm correctly.The membership provider should then be able to use it without issue.
Here's a good article about this topic.
Update
(deep breath) - apologies if this is tl;dr.
Okay, so having read around about BCrypt.Net's password hashing - it's obviously good, and follows accepted practise. It is, also, completely incompatible with how the
HashAlgorithm
class works because it requires additional state in order to work it's magic, and can't simply be extended to implement theHashAlgorithm
contract.Thus, you have a choice - stick with
MembershipProvider
and use SHA512 as you already are - you're talking about beefing up security on a page, so I'm thinking there might be issues with authentication itself, rather than the storage of passwords (which must, of course, still be done properly) - so consider simply making sure that the authentication traffic is sent over HTTPS if it's not already.Using password stretching algorithms blindly has its own issues - see the responses to my own recent SO on this topic - if you do the stretching on the server you could potentially end up causing a DOS attack on the site!
The other option is, as you've suggested, to manage the membership entirely yourself - thus you can use whichever types you want and manage the necessary storage of the password information manually.
My sites now use an algorithm very similar to PBKDF2 that I lifted from Bruce Schneier and Niels Ferguson's book Practical Cryptography, for which I use 512 bit random salt and SHA512 (storage is cheap) plus many thousands of iterations to hash a clear text. The server benchmarks itself once per appdomain to establish 'levels' of protection that equate to millisecond ranges - thus over time newly hashed passwords will receive a constant level of protection even if the hardware improves. The library is standalone, too, and I've been able to deploy it to SQL Server 2008 R2 to provide CLR SPs if we have to generate password records at the SQL level.
But this only protects the passwords - you then need an authentication mechanism that can protect the act of logging in; plus another system for protecting the authenticated session token (.Net's Authentication Cookie system is actually pretty good for this).
Following on from that SO I have now spent a week implementing SCRAM primitives that I have then plugged into my MVC web services for authentication, and I plan to do the same to enable login from the web browser using Javascript (locking out non-JS clients). The key there being the client is doing all the hash calculations; thus I've stuck to SHA because mature implementations are readily available in practically any environment (e.g. we have iPhone apps too - and they need to authenticate as well).
In your case, however, with the existing investment in the MembershipProvider, I would consider 512 bits of SHA plus SSL plus Asp.Net's auth cookie sufficient - so long as the database is really secure(!) and you've got no SQL injection holes in the site.
对于 HashAlgorithm 的 BCrypt 实现,请参阅我对类似问题的回答 在这里。
您需要使用我的答案中的示例代码创建一个签名的程序集,然后根据需要修改您的设置:
For a BCrypt implementation of HashAlgorithm, see my answer to a similar question here.
You would need to create a signed assembly with the sample code in my answer, and then modify your settings as needed:
为了能够注册自定义 hashAlgorythmType,您需要的第一件事是实际实现 哈希算法。如果 BCrypt 实现了它,那是你的幸运日,但显然它没有实现它,所以这是你的问题。
实际上没有解决办法,因为实现 HashAlgorithm 是能够像这样注册它的要求。
因此,您需要做的是围绕 BCrypt 编写一个包装器来实现 HashAlgorithm,或者,如果这是不可能的,则修改 BCrypt 本身来实现它。
除非您真的非常幸运并且 BCrypt 的编写方式很容易进行此类修改,否则可能需要一些不小的努力。
To be able to register a custom hashAlgorythmType, the first thing you need is a type that actually implements HashAlgorythm. If BCrypt implements it, it's your lucky day, but apparently it does NOT implement it, so this is your problem.
There is really no work around for it, as implementing
HashAlgorithm
is a requirement for being able to register it like this.So what you are going to need to do is either write a wrapper around BCrypt to implement
HashAlgorithm
, or, of this is not possible, modify BCrypt itself to implement it.Unless you are really-really lucky and BCrypt is written in a way that easily lend itself to such a modification, it can require some non-trivial efforts.