4
\$\begingroup\$

I need to lock on my AesManaged instance _Aes to call CreateDecryptor() however the CreateDecryptor() method is not thread safe and this function could be called by multiple threads. Is this the correct way to create a disposable object while needing to use a lock on the parent creating the object?

byte[] encryptedTextBlob = GetEncryptedTextBlob();

ICryptoTransform decryptor = null;
lock(_Aes)
{
    decryptor = _Aes.CreateDecryptor();
}

using (decryptor)
using (var encryptedStream = new MemoryStream(encryptedTextBlob))
using (var decrypedStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
using (var textReader = new StreamReader(decrypedStream))
{
    return textReader.ReadToEnd();
}
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

I would say you're not using AES correctly - don't hold on to an instance of it in your class (guessing by the underscore in the name) but rather create it as needed, while holding AES's parameters (the key and IV) in your class:

using (var aes = new AesManaged() { IV = _IV, Key = _Key })
using (var decryptor = aes.CreateDecryptor())
using (var encryptedStream = new MemoryStream(encryptedTextBlob))
using (var decrypedStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
using (var textReader = new StreamReader(decrypedStream))
{
    return textReader.ReadToEnd();
}
\$\endgroup\$
2
  • \$\begingroup\$ I am getting the data from a 3rd party source that has a fixed IV and Key, that is why I used only the one copy of AesManaged, I thought creating all those copies of AesManaged all to be identical would be expensive. \$\endgroup\$ Commented Jan 25, 2013 at 21:11
  • \$\begingroup\$ Understood, I will use that way. I have asked a new question without all of that Aes stuff in the way as I still would like to know the answer to my original question in case I need to use it in another situation. \$\endgroup\$ Commented Jan 25, 2013 at 22:02
2
\$\begingroup\$

Jesse C. Slicer's answer addresses your main concern, but after seeing those multiple using blocks, you might be interested to know that you can create multiple variables in a single using statement. I think this is a bit easier to read, personally:

using (var aes = new AesManaged() { IV = _IV, Key = _Key },
       var decryptor = aes.CreateDecryptor(),
       var encryptedStream = new MemoryStream(encryptedTextBlob),
       var decrypedStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read),
       var textReader = new StreamReader(decrypedStream))
{
    return textReader.ReadToEnd();
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Interesting, I didn't know you could do this. But personally, I think multiple usings are better, because that way, changing the code is easier. \$\endgroup\$
    – svick
    Commented Jan 25, 2013 at 19:16
  • 1
    \$\begingroup\$ Awesome. I love this. Addresses the primary concern I had with Jessie's answer (which is great, and readable, but I don't like leaving out braces...in fact, they're required by our coding standards.) \$\endgroup\$
    – Beska
    Commented Jan 25, 2013 at 21:49
  • \$\begingroup\$ @Beska the best part is it's been part of the standard for a long time: msdn.microsoft.com/en-us/library/yh598w02(v=vs.71).aspx \$\endgroup\$ Commented Jan 25, 2013 at 22:11
  • 1
    \$\begingroup\$ @svick I see your point, but I think it would be too easy to accidentally an inject somewhere in the using cascades -- still totally valid c#, but altering the meaning of the program: \$\endgroup\$ Commented Jan 25, 2013 at 22:18
  • \$\begingroup\$ @ReacherGilt Unfortunately, this doesn't actually work in older .NET versions. Yes, you can do multiple usings seperated by commas back in VS 2003, like in your example and in the link...but it seems the types have to be the same, which limits the usefulness considerably. I assume this problem isn't encountered in later versions because of the user of the var type for all the variables in your example. \$\endgroup\$
    – Beska
    Commented Jan 29, 2013 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.