Reference implementation of C# password hashing and verification

Given your new "government approved" requirement, my guess is that one good solution would be PBKDF2 from RFC 2898. It is implemented for .NET in Rfc2898DeriveBytes Class (System.Security.Cryptography). You presumably want to substitute SHA-256 for SHA-1 in there.

I also just ran across the Fairly Secure Hashed Password: fshp which is like PBKDF1 but with SHA-256 by default. It supports a variable number of iterations, defaulting to 4096. It uses 64 bit salts. They have implementations there for .NET, Python, Ruby, Perl, PHP5, Java and JavaScript.

As described and discussed at .net impl of bcrypt - Stack Overflow, it seems that for .NET/CLR another good option (though not NIST-approved) is BCrypt.net:

  • Derek Slager: BCrypt.net - Strong Password Hashing for .NET and Mono

and for Java a good option is

  • jBCrypt - strong password hashing for Java

I guess neither seems to have the "pepper" concept, or the space complexity of scrypt.


The basics

The basic approach is Hash(secret | salt), which is stored along with the salt. Obviously it's important to use a modern hash algorithm like one of the SHA2 variants (though currently SHA1 is not totally broken like MD5 is). Note that if you are storing challenge questions this way, you probably want to Trim() and ToLower() the secret before hashing it. This may reduce the complexity somewhat, but security questions aren't intended to have high entropy like a password anyway.

What about brute-force attacks like Rainbow tables?

Concerns about brute-force attacks can be mitigated in two ways:

  1. Require a minimum amount of entropy in the secret (length, complexity, etc.).
  2. Increase the amount of computation required to perform the hash.

The method used in bcrypt is a good improvement on standard hashing because it increases the amount of time to calculate the hash by many orders of magnitude. Basically, it just iteratively hashes the secret many times: Hash(Hash(...Hash(secret | salt)...))

Because the amount of time is still relatively small (hundreds of milliseconds), it does not add an intolerable delay to the legitimate user. But it can ruin automated brute-force attacks.

That's not good enough

If the additional difficulty of bcrypt is insufficient, try scrypt. It works like bcrypt but needs to save each iterative hash in memory for a final merge at the end. This adds the same time complexity as bcrypt but also increases space complexity, making it more difficult to implement in hardware, especially in parallel.

Implementation

Honestly, I'm not aware of a C# library to implement this, let alone one "certified" by some official body, but it wouldn't be too difficult. Assuming you write thread-safe code, and the password verification takes place on a trusted system like a server, implementation concerns like side-channel attacks are minimized.

Further reading: This answer to Is BCrypt a good encryption algorithm to use in C#? Where can I find it?