Skip to content

Password management made easy in ASP.NET with the Crypto API

October 19, 2012

If you are building your own database of credentials then you need to store passwords. I won’t go into the details of why (but you can read them here), but the modern way of doing it is with password stretching (or iterative hashing) using the Rfc2898DeriveBytes class. This class generates a salt and then uses that to hash the password but instead of once it does it in a loop for a certain number of iterations (1000 or 10000 or whatever). This is a stronger way to store passwords compared to a single hash because it slows an attacker down if they are trying to generate a rainbow table to brute force the hashed password. If you’ve never used this class before then it can be a little confusing. Fortunately in ASP.NET (via the Crypto class in System.Web.Helpers.dll) they provide a wrapper on this and so you don’t even have to get involved with the details. Here’s how you would use this when creating a new account for a user using Crypto.HashPassword:

public void CreateAccount(string username, string password)
{
    var hashedPassword = Crypto.HashPassword(password);
    CreateAccountInDatabase(username, hashedPassword);
}

The beauty here is that the returned value contains both the salt and the hashed password in a single value. All you need to do is store the username and hashed password in your database.

Another consideration when doing your own password management has to do when you are validating credentials on a login page. Of course we’ll need to re-run the hashing algorithm to validate a password provided by the user. We then compare the hashed password from the user to the hashed password stored in the database.The work is also provided by the Crypto class via Crypto.VerifyHashedPassword:

public bool ValidateCredentials(string username, string password)
{
    var hashedPassword = GetPasswordFromDatabase(username);
    var doesPasswordMatch = Crypto.VerifyHashedPassword(hashedPassword, password);
    return doesPasswordMatch;
}

One subtle issue that’s not obvious here is that we don’t want to use the normal string comparison (== operator) when comparing password values. The reason is that normal string comparison will exit as soon as the first character mismatch is encountered and this can leak information to an attacker. Fortunately the implementation inside of Crypto.VerifyHashedPassword does not use the normal string comparison and always does a full character-by-character comparison to not leak this side channel information. It’s really done quite well.

So if you’re not using the membership provider then you need to manage passwords, and this can be done easily and securely with the Crypto class. Kudos to Microsoft for this API.

16 Comments leave one →
  1. Erik permalink
    October 19, 2012 3:36 pm

    Can you explain more about the “information leak” when using the == operator? If I get your meaning, you are saying that you may be able to detect that the first x characters are correct when trying to do a brute force?

    I guess that may be the case with some forms of cryptography, but it certainly shouldn’t be the case with hashed passwords, as changing even one character ends up with a radically different hash.

  2. October 19, 2012 11:37 pm

    Though it’s probably quite similar to what’s baked in the MS API, there’s a good overall implementation of all of this (including SlowEquals) to be found here: http://crackstation.net/hashing-security.htm

  3. humba permalink
    April 15, 2013 9:16 am

    hi, use the ms implementation sha-1 per default? if so the cracking is not hard as http://www.troyhunt.com/2012/06/our-password-hashing-has-no-clothes.html states.

    • April 15, 2013 9:54 am

      @humba, sorry I’m not sure what you’re asking or trying to say.

  4. April 29, 2013 6:31 am

    According to the documentaiton, Crypto.HashPassword only uses 1000 iterations to create the password. That was the minimum recommended value for 2000 so it is not creating hashes that you would still consider secure.

  5. Greg permalink
    September 19, 2013 6:11 pm

    I’m not clear on why you’d want to use an API that’s distributed with WebMatrix as opposed to the API in the .NET Framework (namely System.Security.Cryptography). I mean, I guess it’s easier to use, but isn’t there always a trade-off with investing time in MS products that might have a short shelf-life?

    • September 22, 2013 7:59 am

      The API is part of the ASP.NET webstack (so it’s not solely distributed with WebMatrix). And all it does is sit on top of the crypto APIs you suggest.

      The real reason to use it is because most developers are not security developers and thus probably shouldn’t be writing security code (without review by someone who knows what they’re doing). This is true no matter what programming environment you’re in.

  6. February 25, 2015 10:23 am

    @brockallen I did some research into this as I was working on a VB project and wanted to use the security. I stubled upon the src here: http://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Core/2.0.0-rtm-140327/Release/Default/Microsoft.AspNet.Identity.Core/Microsoft.AspNet.Identity.Core/Crypto.cs?ImageName=Microsoft.AspNet.Identity.Core
    It seem Crypto.VerifyHashedPassword() checks the byes arrays are equal, NOT the password strings.

  7. bomberzocker permalink
    March 26, 2017 4:57 pm

    Thank you so much, exactly what I was looking for.

Trackbacks

  1. Beheben Crypto Api-fehlercodes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: