Generating and verifying password hashes

Edit:This password utilities library has now been substantially upgraded and open-sourced with an MIT license. You can find a .NET 4.0 version of the library and an example graphical interface in a Google Code Mercurial repository.

This is the sixth installment in a series about creating a C# password utilities library.

The next step is to implement the password salting, hashing, and stretching.

The constructors of the HashGenerator.cs class let you specify the default hash policy or your own policy. As discussed last time, a policy consists of the salt length in bytes, the hash length in bytes, and how much the password should be stretched (number of hash iterations).

Once you've specified the password, the code creates a random salt and passes the password, salt, and number of hash iterations into a method that creates and returns the salted hash.

To create the random salt, we go back to our old friend RNGCryptoServiceProvider, the basis of the dice implementation that we discussed earlier. The GetBytes function returns a set of cryptographically-secure random bytes. It's actually overkill for this purpose, because the salt randomness doesn't need to be that secure.

To create the salted hash, we're going to use the .NET Framework's implementation of a key derivation function called PBKDF2, also published as RFC 2898. PBKDF2 has some useful properties: you can use a salt, you can define the hash output size, and you can configure the slowdown factor by specifying the number of iterations over the hash function.

At this point, we're done with the salting, hashing, and stretching. It would be nice to return the salt, the hash, and the number of hash iterations in a single package. This package can then be stored, and used later to verify whether a password and stored salt matches the stored hash. To do this, we return a string containing an ASCII string in the format XXXX.9999.YYYYXXXX is the salt encoded as a base-64 string, 9999 is the number of iterations of the hashing function, and YYYY is the hash encoded as a base-64 string.

The final step is to verify a password against a stored salt and hash. To do this, you specify the password along with the stored salt, hash, and number of iterations. The latter can be passed as a single package in the format XXXX.9999.YYYY as discussed above. Or you can pass everything as separate parameters. The salted password is iteratively hashed before being compared to the supplied hash. If the two hashes match, the password is correct.

You can view and download HashGenerator.cs. The complete library, including this class, will be posted at the end of this series. In the next installment, we'll look at the EntropyChecker.cs class, which attempts to measure the information entropy of randomly-generated and human-generated passwords. The information entropy is a reasonable proxy for the password strength.