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

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 inSystem.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 viaCrypto.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.

Advertisements

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