0

I know there is plenty of this questions with answers around but I have spent hours and hours googleing and have tried all suggestions that I have found.

I download a file and I want to store it encrypted in the isolated storage. This is how I store it:

                        using (var fs = new IsolatedStorageFileStream(fileName, FileMode.Create, store))
                        {
                            byte[] bytesInStream = new byte[args.Result.Length];
                            args.Result.Read(bytesInStream, 0, bytesInStream.Length);

                            var aes = new AesManaged
                                        {
                                            Key = GetBytes("aaaaaaaa"),
                                            IV = GetBytes("bbbbbbbb")
                                        };

                            byte[] encryptedArray;
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
                                {
                                    cryptoStream.Write(bytesInStream, 0, bytesInStream.Length);
                                    cryptoStream.FlushFinalBlock();

                                    encryptedArray = memoryStream.ToArray();
                                }
                            }

                            fs.Write(encryptedArray, 0, encryptedArray.Length);
                            fs.Flush();
                        }

The following code is for reading the file from isolated storage and decrypt it:

                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(fileName))
                    {
                        var file = store.OpenFile(fileName, FileMode.Open,FileAccess.Read,FileShare.Read);
                         var reader = new BinaryReader(file);

                         var aes = new AesManaged
                         {
                               Key = GetBytes("aaaaaaaa"),
                               IV = GetBytes("bbbbbbbb")
                         };

                         byte[] decodedContent;
                         byte[] encodedContent = reader.ReadBytes(1280);
                         using (MemoryStream ms = new MemoryStream(encodedAudio))
                         {
                             using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
                             {
                                   BinaryReader r= new BinaryReader(cs);
                                   decodedContent= r.ReadBytes(encodedContent.Length);
                            }
                         }
                }

When the program reaches this line: decodedContent= r.ReadBytes(encodedContent.Length); I get CryptographicException with the following message: Padding is invalid and cannot be removed.

Can anyone help me with this issue?

vladtamas
  • 51
  • 4

2 Answers2

0

You can't decrypt by blocks because silverlight AesManaged always include padding and if you read only a part of encrypted block - decryption class can't find the padding that should be removed. You can decrypt whole data only. Alternatively, you can split the data manually in the encryption part of your algorithm. Hans Passant told you the same, just in a short form ;)

crea7or
  • 4,421
  • 2
  • 26
  • 37
0

You can decrypt 1,280 bytes at a time, if you decrypt without removing padding until the last block. That is, you have to set the decryptor to not remove padding (i.e. "no padding") on all but the last block.

I.e. when there are N blocks:

  • for blocks 1 to N-1: decrypt(1280 bytes, no padding)
  • for block N: decrypt(however many bytes left, padded)

You can also run the entire decryption with "no padding" and strip the padding yourself. The last byte will give you the number of bytes to clip from the end, from 1 to 16.

If you cannot turn off padding-removal on decryption (implied by your comment above), you can still decrypt 1,280 bytes at a time. Just encrypt the blocks individually. They will each get padding, and make it fit 1,280. For example, encrypt 1,279 bytes at a time (each block is given a 1 byte pad.) Encrypting the full 1,280 with padding will give you 1,296 bytes (a multiple of 16 bytes of plaintext is going to get a full 16-byte pad.)

Edit, for the interested:

If you find yourself with a large ciphertext, and you want to decrypt it in blocks, and for some reason your decryption is constrained such that you are forced to use padding mode PKCS#7, you can still decrypt the data a block at a time. It's a bit more expensive -- it will cost you an extra encryption of 16 bytes per block, but at least it is possible.

Take each block of raw ciphertext, and encrypt a little tail of 16 bytes for each block which is correctly padded for that block. Then decrypt the enlarged block, and finally, remove the extra bit of data used to encrypt the padding tail.

You just take the last 16 bytes of the block as your IV, and using the same key, encrypt some small data -- for example a single byte -- padded with PKCS#7. Attach the 16 byte result of the encryption to the block and now decrypt the block + 16 bytes. The padding is removed from the tail 16 bytes, and you can remove the bit of data, and end up with the original block of plaintext. See more in my answer here

Community
  • 1
  • 1
Jim Flood
  • 8,144
  • 3
  • 36
  • 48