views:

135

answers:

3

I've run into an interesting issue.. It seems that ComputeHash() for a "HMACSHA256" hash is not behaving deterministicly.. if I create two instances of HashAlgorithm using HashAlgorithm.Create("HMACSHA256").. And run ComputeHash, I get two different results.. below is an example static class that exhibiting this behavior.

    internal static string HashPassword(byte[] bAll)
    {
        using (HashAlgorithm s = HashAlgorithm.Create("HMACSHA256"))
        {
            return Convert.ToBase64String(s.ComputeHash(bAll));
        }
    }

I've also tried to make the call non static (actually it started non static, and I have double and triple and quadrudruple checked my input array.. its absolutely the same on each call.. I've even done stuff in the immidiate window like Convert.ToBase64String(HashAlgorithm.Create("HMACSHA256").ComputeHash(bAll)... And running that twice in the immidiates window via a breakpoint in the method returns two different hashes..

I know Hash is suppose to be deterministic.. So what gives? is something going on with running in a debugger? Or any other ideas? really this is just two weird for words right now :-P..

Thanks Josh

+12  A: 

HMAC is a keyed hash. I don't see the key in your example code.

HashAlgorithm.Create("HMACSHA256") creates a HashAlgorithm instance, so it doesn't know anything about a key. It probably just calls this HMACSHA256 Constructor:

public HMACSHA256()

Initializes a new instance of the HMACSHA256 class with a randomly generated key.

You want this constructor:

public HMACSHA256(byte[] key)

Initializes a new instance of the HMACSHA256 class with the specified key data.

If you don't want to to hard-code the HMAC algorithm, you can use KeyedHashAlgorithm.Create and supply a specific key by setting the KeyedHashAlgorithm.Key property.

If you don't want to use a key, then use a non-keyed hash like SHA256.

dtb
His best bet is to use [`KeyedHashAlgorithm.Create`](http://msdn.microsoft.com/en-us/library/s5zz2x4d.aspx). Lesson learned: know your hashes!
Randolpho
I'm going to digg into the provider stuff and figure out why MS was/is defaulting to a keyed hash, but using HashAlgorithm.Create() when the gen it. it may be that I am using 2.0 based ASP.NET Provider starter pack source with 4.0 framework.. Anyways, thanks for pointing me in the right direction.
Josh Handel
@Josh: There are a few places where MS had "surprising" randomness. For example, some `CypherMode` settings for encryption use a random Initialization Vector if you don't specify. The fun part is when your Encryption and Decryption work perfectly for all but the first 8 bytes of your data. I think they made a good decision here. I'd rather a program fail fast because I don't understand the security parameters it needs than have it default to a "working" but less secure state.
Brian
+2  A: 

You need a Key for HMACSHA256. The key will be random if it is not passed into the constructor.

DaveShaw
A: 

Just adding to this in hopes to save someone the headache I went through.

In the case of .Net Membership Provider, make sure you have the setting in your web.config or app.config. Else it will automatically generate its own key... crap out on authentication, and then belligerently laugh at you in the end.

Jon