1

I'm porting an app from Node to ASP.NET Core, and discovered that the .NET Core framework doesn't have a bcrypt implementation. There are community supported bcrypt implementations but they are very old or have not undergone review, like those written by Microsoft - so I'd prefer a "worse" algorithm that has MS' backing.

The System.Security.Cryptography namespace has lots of algorithms to choose from.

bcrypt is the preferred password hashing algorithm in the Node ecosystem - it also has various features like the "slowness" and workfactor and handy salting routines. I hope I don't have to give up too much when choosing something else.

I'm not a hashing expert - which is the best alternative password hashing algorithm from that link? (Which will get me as close as possible to what I'm used to with bcrypt.)

  • 2
  • @Xander PBKDF2... Does it do that workfactor "slowdown" like bcrypt does? – lonix Apr 26 '19 at 17:53
  • Yes, it does. That's the iterationCount parameter. – Xander Apr 26 '19 at 17:54
  • 1
    @Xander Thanks! Now I need to write code for converting the old membership database to the new... fun times. :) – lonix Apr 26 '19 at 17:55
6

The preffered algorithm from that namespace seems to be PasswordDeriveBytes, though this is PBKDF1, which is nowhere as good as Bcrypt and probably should not be used.

PBKDF2 from a different namespace is probably preferable. Just note that the work factor there is linear, not exponential like in BCrypt and should be quite large.

I would consider using Argon2 from LibSodium with a C# wrapper. Libsodium is a reputable and well maintained library focused on ease of use.

| improve this answer | |
  • Alternatively, just use the extremely active bcrypt.net project. It's completely fine. – Stephen Touset Apr 26 '19 at 18:00
  • 1
    @lonix almost certainly yes. Honestly, the main point of my answer is use Libsodium if at all possible. Argon2 is much better then PBKDF and possibly even better than bCrypt. – Peter Harmann Apr 26 '19 at 18:02
  • 1
    You should not use PBKDF1. But you should also just use the argon2 implementation in libsodium or bcrypt.net. – Stephen Touset Apr 26 '19 at 18:02
  • 2
    @lonix well, it is a gamble using a smaller project like that. Just because it is active now does not mean it will be in a few years. Libsodium is so widely used in many programing languages, that it will likely remain supported for a very long time. – Peter Harmann Apr 26 '19 at 18:04
  • 1
    @lonix well the great thing about libsodium is that the core is alwas C and the unmaintained part is just the wrapper for C#, where there is not much chance to mess up. While there may be issues with it not being maintained, it is unlikely they will compromise security and libsodium as such has maintanance and extended usage. Not sure about review right now but I thought it had one. – Peter Harmann Apr 26 '19 at 19:32
2

What you can use in .NetCore is Rfc2898DeriveBytes that implements PBKDF2 but it is unfortunately a bit low level and hard to use.

I have made a library SimpleHashing.Net that makes use of Rfc2898DeriveBytes in .Net easier. The interface that resembles the one of bcrypt and as easy to use (it is possible to set the number of iterations as well). It's available on nuget.

P.S. I did not implement crypto, just wrapped the existing Microsoft implementation to be able to use it in an easy way, e.g.:

ISimpleHash simpleHash = new SimpleHash();

// Creating a user hash, hashedPassword can be stored in a database
// hashedPassword contains the number of iterations and salt inside it similar to bcrypt format
string hashedPassword = simpleHash.Compute("Password123");

// Validating user's password by first loading it from database by username
string storedHash = _repository.GetUserPasswordHash(username);
bool isPasswordValid = simpleHash.Verify("Password123", storedHash);
| improve this answer | |
  • It was stated above already that PasswordDerivedBytes is PBKDF1 which should not be used. I edited my answer to make it explicit – Peter Harmann Jan 15 at 16:38
  • 1
    I made an error, it is Rfc2898DeriveBytes that I use, I'll fix the answer. I thought it's the same thing and forgot the name of the class, apparently it is not :) – Ilya Chernomordik Jan 15 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.