When trying to reuse the ICryptoTransform
objects during Encryption and Decryption using the AesCryptoServiceProvider
there is a 'bug' that is fixed by upgrading the .NET framework version of an application to 4.6.2.
This stack overflow post (Reuse ICryptoTransform objects) and microsoft github page showing .net version release notes (https://github.com/Microsoft/dotnet/blob/master/Documentation/compatibility/aescryptoserviceprovider-decryptor-provides-a-reusable-transform.md) explains this bug and how to fix it. For the most part, this seems to as expected when I upgrade my application(s) to .NET version 4.6.2, with a slight gotcha for ASP.NET applications - solution mentioned in one of the stack overflow comments.
However, when trying to achieve this fix for an Azure Cloud Service, the behavior exhibited is as if the framework was not updated, not matter if the context switch is present or if the project is upgraded to .NET 4.6.2.
- When reusing the
ICryptoTransform
object, the string output from theDecrypt
method is corrupted. - The context switch (when added into the app.config of the CloudService) is ignored when used.
Note I have only tested this using the local emulator and have also tried the following.
- Reinstalling the Nuget packages
- Upgrading to .NET 4.7
- Using the appconfig context switches as suggested in the release notes.
- Creating a new cloud service, the behaviour is the same.
Can anyone confirm this same behaviour? Is there a special case for Azure Cloud Services with regards to upgrading the .NET framework? Perhaps a certain app.config setting is required that i am not aware of?
Code Sample
private ICryptoTransform _decryptorTransform;
private ICryptoTransform DecryptorTransform
{
get
{
if (null == _decryptorTransform || !_decryptorTransform.CanReuseTransform)
{
_decryptorTransform?.Dispose();
using (var aes = GetNewCryptoProvider())
{
_decryptorTransform = aes.CreateDecryptor();
}
}
return _decryptorTransform;
}
}
public string Encrypt(string plainText, EncodingType type)
{
byte[] encrypted;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, EncryptorTransform, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
string encryptedString = "";
if (type == EncodingType.Base32)
encryptedString = Base32.Encode(encrypted);
else if (type == EncodingType.Base64)
encryptedString = Convert.ToBase64String(encrypted);
else
throw new NotImplementedException();
if (_azureStorageSafe)
return encryptedString.Replace('/', '|').Replace('+', '-');
else
return encryptedString;
}
private AesCryptoServiceProvider GetNewCryptoProvider()
{
var aes = new AesCryptoServiceProvider();
aes.Key = keyBytes;
aes.IV = ivBytes;
aes.Padding = PaddingMode.Zeros;
aes.Mode = CipherMode.CBC;
return aes;
}