Adding a custom hashAlgorithmType in C# ASP.NET

眉间皱痕 提交于 2019-12-03 08:48:29
Andras Zoltan

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 calling HashAlgorithm.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 the HashAlgorithm 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.

GalacticJello

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:

<cryptoNameMapping>
  <cryptoClasses>
    <cryptoClass MyHash="BCryptHasher, MySignedAssemblyName
                 Culture=neutral, PublicKeyToken=<my public key for singed assembly>,
                 Version=1.0.0.0"/>
  </cryptoClasses>
  <nameEntry name="System.Security.Cryptography.HashAlgorithm" class="MyHash"/>
</cryptoNameMapping>

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!