Context: The HMAC object is not thread-safe, but having only one HMAC object across n-threads requires locking during a frequent operation during handshake, so alternative approaches that manage an HMAC object per thread were explored. This solution provides an alternative to using the [ThreadStatic] attribute, which creates some problems during disposal and key synchronization.
Proposed Solution:
A helper class was added to manage the responsibility of HMAC objects and their thread distribution. The helper:
-Provides simple properties for accessing the calling thread's current HMAC objects
-Lazily initializes the thread's HMAC objects
-HMAC getters are lockless in the general case (CurrentDictionary reads)
-Manages key rotation with a timer
-Key generation uses cryptographically safe random and synchronized across all threads
-Dispose is thread-safe*
*My only critique is that, to prevent locking, I had to add another hmac rotation hmacToDispose as a thread might be using a previousHmac while a key rotation is happening (so we can't call previousHmac.Dispose() during rotation). However and regardless, this assumes that the calling threads do not hold their references to the HMAC objects for a long time, which if they did, could lead to an ObjectDisposedException
Context: The HMAC object is not thread-safe, but having only one HMAC object across n-threads requires locking during a frequent operation during handshake, so alternative approaches that manage an HMAC object per thread were explored. This solution provides an alternative to using the [ThreadStatic] attribute, which creates some problems during disposal and key synchronization.
Proposed Solution: A helper class was added to manage the responsibility of HMAC objects and their thread distribution. The helper: -Provides simple properties for accessing the calling thread's current HMAC objects -Lazily initializes the thread's HMAC objects -HMAC getters are lockless in the general case (CurrentDictionary reads) -Manages key rotation with a timer -Key generation uses cryptographically safe random and synchronized across all threads -Dispose is thread-safe*
*My only critique is that, to prevent locking, I had to add another hmac rotation
hmacToDispose
as a thread might be using apreviousHmac
while a key rotation is happening (so we can't call previousHmac.Dispose() during rotation). However and regardless, this assumes that the calling threads do not hold their references to the HMAC objects for a long time, which if they did, could lead to an ObjectDisposedException