It is worth knowing that KeyedHashAlgorithm.ComputeHash() not thread safe because it gives a non-deterministic result for the same KeyedHashAlgorithm.Key .
In my case, I want to cache KeyedHashAlgorithm, since my KeyedHashAlgorithm.Key always the same to authenticate from the client side. I understand that ComputeHash() not consistent, maybe it caches an internal variable in an instance of KeyedHashAlgorithm . I have to cache the instance on a ThreadStatic or ThreadLocal thread. This is a test:
Static KeyedHashAlgorithm gives inconsistent result:
var kha = KeyedHashAlgorithm.Create("HMACSHA256"); kha.Key = Encoding.UTF8.GetBytes("key"); Action comp = () => { var computed = kha.ComputeHash(Encoding.UTF8.GetBytes("message")); Console.WriteLine(Convert.ToBase64String(computed)); }; Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);
Compared to KeyedHashAlgorithm for a stream:
ThreadLocal<KeyedHashAlgorithm> tl= new ThreadLocal<KeyedHashAlgorithm>(() => { var kha = KeyedHashAlgorithm.Create("HMACSHA256"); kha.Key = Encoding.UTF8.GetBytes("key"); return kha; }); Action comp = () => { var computed = tl.Value.ComputeHash(Encoding.UTF8.GetBytes("message")); Console.WriteLine(Convert.ToBase64String(computed)); }; Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);
This code can be used to test other functions for the result of "thread safety". Hope this helps others.
source share