The default password hasher for ASP.NET Core Identity uses PBKDF2 for password hashing. Whilst this is a decent enough implementation, there are certainly more desirable password hashing algorithms out there. So that’s exactly what I’ve addressed, with three new password hasher implementations for ASP.NET Core Identity using bcrypt, scrypt, and Argon2.
Default (PBKDF2) Password Hasher
To be precise, the ASP.NET Core Identity uses PBKDF2 with HMAC-SHA256, a 128-bit salt, a 256-bit subkey, and (by default) 10,000 iterations. Luckily this iteration count is now configurable (unlike ASP.NET Identity 2), and realistically you’ll be looking at adding another zero to that iteration count. 10,000 iterations is so 2012.
PBKDF2 is generally considered “good-enough”, assuming you use a high number of iterations and a SHA2 family hash function. It is also FIPS compliant and recommended by NIST. However, it is not so secure against newer attack vectors, such as GPU based attacks, and is often considered weak compared to alternatives as a result.
If you’re interested in learning more about the default PBKDF2 password hasher, check out Andrew Lock’s article “Exploring the ASP.NET Core Identity PasswordHasher”.
Alternatives to PBKDF2
Around the internet, you’ll typically find the following list of password hashing algorithm strength:
- Argon2 (winner of the Password Hashing Competition)
- Catena, Lyra2, Makwa, or yescrypt (honourable mentions in the Password Hashing Competition)
With Argon2 leading the list but with the caveat that it’s still relatively “new”, and bcrypt & scrypt fighting for the number 2 spot (with bcrypt typically winning). PBKDF2 still gets a mention if FIPS compliance is top of your priorities.
I’m not going to go into further detail as to why these are ranked like they are, or into the benefits of each one over PBKDF2, as this is a topic unto itself. Instead, give it some research as there are lots of interesting discussions out there. I personally found the following links a good starting point:
- Do any security experts recommend bcrypt for password storage?
- How to Safely Store Your Users' Passwords in 2016
Custom Implementations of IPasswordHasher
To improve the story for password hashing in ASP.NET Core, I’ve created some IPasswordHasher implementations that use open source libraries to hash and verify passwords. At the moment these have been designed for new projects only, with no migration/rehash functionality. If you’re keen on seeing this, let me know.
You can find installation instructions for each on their respective GitHub repositories. All options default to the defaults used by their underlying crypto libraries. If some of these are outdated, feel free to create a pull request.
Bcrypt Password Hasher
The bcrypt password hasher uses Chris McKee’s bcrypt.net – next, an updated and maintained version of the original BCrypt.Net port of jBCrypt.
This was the easiest password hasher to implement since the API makes sense, and the library has been kept up to date with .NET Standard.
- Repository: ScottBrady91.AspNetCore.Identity.BCryptPasswordHasher
- OSS Library: BCrypt.Net
Argon2 Password Hasher
The Argon2 password hasher uses libsodium-core, which is a .NET Standard port of libsodium-net, which is a C# wrapper around libsodium. I’ll eventually update the hasher to use the original libsodium-net library, once it has been ported to .NET Standard 2.0.
- Repository: ScottBrady91.AspNetCore.Identity.Argon2PasswordHasher
- OSS Library: libsodium-core
Scrypt Password Hasher
The scrypt password hasher uses scrypt.net, a .NET port of the original implementation in C.
- Repository: ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher
- OSS Library: scrypt.net
Like these packages or have a feature request? Then let me know! Or better yet, make a pull request and work with me to help improve the security options for ASP.NET Core Identity.
Stalwart fan of PBKDF2 and mortally insulted by my sweeping remarks? Then join the discussion on Information Security Stack Exchange or other infosec communities to make PBKDF2 great again.