views:

218

answers:

1

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:

  1. 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?

  2. 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?

  3. Potentially the most important question, in a highly multithreaded environment, will I run into issues with sharing the ICryptoTransform objects between threads?

  4. 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.)

  5. 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!

+6  A: 

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.

Reed Copsey
Good sound advice. I guess I made the assumption that creating and destroying some of these objects came at a cost due to the underlying dependencies upon the navtive Platform SDK classes. If no one thinks this is a warranted concern, then it sounds like the synchronization mechanisms might in the end be the bigger bottleneck.
McKAMEY