-2

I implement the following method:

public static byte[] AESDecrypt(byte[] data, ICryptoTransform transform)
    {
        using (MemoryStream stream = new MemoryStream(data))
        using (CryptoStream cstream = new CryptoStream(stream, transform, CryptoStreamMode.Read))
        using (MemoryStream output = new MemoryStream())
        {
            byte[] buffer = new byte[4000];
            int r;
            while ((r = cstream.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, r);
            }
            stream.Close();
            return output.ToArray();
        }
    }

I am using this method to decrypt a sequence of 16 bytes blocks, the transform parameter is initialized once at the beginning:

AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
provider.Mode = CipherMode.ECB;
provider.KeySize = 128;
provider.BlockSize = 128;
provider.Key = key;
provider.Padding = PaddingMode.PKCS7;
transform = provider.CreateDecryptor();

My problem is that suddenly the method starts to produce strange output, 16 bytes block is decrypted to 27 bytes !!!!, sometimes 16 bytes are decrypted wrongly to 16 bytes, however when I restart the application the same data produce correct result, does the transform hold any state that makes this happen? what wrong thing I did that makes 16 bytes block decrypted to 27 bytes.

Any help is appreciated

`Edit:

Can someone confirm it is the same bug: Reuse ICryptoTransform objects

Edit 2:

Something to add to the correct answer:

It seems ICryptoTransform is not thread safe, so calling the above method from two threads simultaneously may cause trouble, I solved it by creating ICrypteTransform object for each thread that is using the method

ammcom
  • 992
  • 1
  • 7
  • 24
  • No it is the same, however I found this https://stackoverflow.com/questions/43593495/reuse-icryptotransform-objects/43598850 – ammcom Jun 19 '17 at 14:25
  • Anyway I am telling you that 16 bytes are decrypted to 27 bytes, what does make it related to my date?????? your comment is not suitable – ammcom Jun 19 '17 at 14:30

1 Answers1

3

You are closing stream when you meant to close cstream.

Since you don't close cstream before reading out the data, TransformFinalBlock is never called.

You'd be better off using Stream.CopyTo, and making your output stream have a clearer longer-lifetime than the CryptoStream.

public static byte[] AESDecrypt(byte[] data, ICryptoTransform transform)
{
    using (MemoryStream output = new MemoryStream())
    {
        using (MemoryStream stream = new MemoryStream(data))
        using (CryptoStream cstream = new CryptoStream(stream, transform, CryptoStreamMode.Read))
        {
            cstream.CopyTo(output);
        }

        return output.ToArray();
    }
}
bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • Thank you for information but as in know decryption does not involve calling TransferFinalBlock as all the input is always divided by 16 (this is the benefit of padding). any way thank you for the note – ammcom Jun 19 '17 at 16:19
  • 2
    @ammcom TransformFinalBlock is responsible for removing any padding, as well as resetting the ICryptoTransform. It's very important to ensure it gets called, or your output gets pretty jangly. – bartonjs Jun 19 '17 at 16:22