I have a high-level goal of creating a static utility class that encapsulates the encryption for my .NET application. Inside I'd like to minimize the object creations that aren't necessary.
My question is: what is the thread-safety of the classes which implement symmetric encryption within the .NET Framework? Specifically System.Security.Cryptography.RijndaelManaged
and the ICryptoTransform
types it generates.
For instance, in my class constructor can I simply do something along the following lines?
static MyUtility()
{
using (RijndaelManaged rm = new RijndaelManaged())
{
MyUtility.EncryptorTransform = rm.CreateEncryptor(MyUtility.MyKey, MyUtility.MyIV);
MyUtility.DecryptorTransform = rm.CreateDecryptor(MyUtility.MyKey, MyUtility.MyIV);
}
}
Side-stepping the issue of is it secure to have Key and IV exist within this class, this example block brings up a number of other questions:
Can I continually reuse the EncryptorTransform and DecryptorTransform over and over? The *.CanReuseTransform
and *.CanTransformMultipleBlocks
properties imply "yes", but are there any caveats I should be aware of?
Since RijndaelManaged
implements IDisposable
my inclination is to put it within a using
block especially since it probably ties into external OS-level libs. Are there any caveats with this since I'm keeping the ICryptoTransform
objects around?
Potentially the most important question, in a highly multithreaded environment, will I run into issues with sharing the ICryptoTransform
objects between threads?
If the answer to #3 is that it isn't thread-safe, will I experience serious performance degradation from locking while I use the ICryptoTransform
objects? (Depends on load I suppose.)
Would it be more performant to simply instantiate new RijndaelManaged
each time? Or store one RijndaelManaged
and generate new RijndaelManaged().CreateEncryptor(...)
each time?
I am hoping that someone out there knows how these work under the hood or are experienced with issues from similar implementations. I've found that a lot of these kinds of performance and thread-related issues typically do not manifest themselves until there is a sizable amount of load.
Thanks!
1) Yes.
2) One you dispose of it, you cannot use it. Up until then, you can share/use it (but see below)
3-4) From MSDN:
"Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe. "
If you want to keep this around, and share it between threads, you'll need to implement locking and treat it as a locked resource. Otherwise, I'd recommend just making separate versions as needed, and disposing of them when you're done.
5) I would recommend creating these as needed, and then trying to optimize it if later you find you have a performance problem. Don't worry about the performance implications of creating a new version until you see that's its a problem after profiling.