C#AesManaged Exception:填充无效,无法删除

时间:2014-04-09 17:25:18

标签: c# windows-phone-8 cryptography isolatedstorage

我知道有很多这样的问题和答案,但我花了几个小时google并尝试了我找到的所有建议。

我下载了一个文件,我希望将其加密存储在独立存储中。 这就是我存储它的方式:

                        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();
                        }

以下代码用于从隔离存储中读取文件并对其进行解密:

                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);
                            }
                         }
                }

当程序到达这一行时: decodingContent = r.ReadBytes(encodedContent.Length); 我收到 CryptographicException ,并显示以下消息:填充无效且无法删除。

任何人都可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

您无法通过块解密,因为Silverlight AesManaged始终包含填充,如果您只读取加密块的一部分 - 解密类无法找到应删除的填充。您只能解密整个数据。或者,您可以在算法的加密部分手动拆分数据。汉斯·帕斯特(Hans Passant)也以同样的简短形式告诉过你;)

答案 1 :(得分:0)

如果解密而不删除填充直到最后一个块,则可以一次解密1,280个字节。也就是说,您必须将解密器设置为而不是删除除最后一个块之外的所有内容的填充(即“无填充”)。

即。当有N个街区时:

  • 对于块1到N-1:解密(1280字节,无填充)
  • 对于块N:解密(但是剩下很多字节,填充)

您还可以使用“无填充”运行整个解密并自行剥离填充。最后一个字节将为您提供从结尾剪辑的字节数,从1到16。

如果您无法在解密时关闭填充删除(上面的注释暗示),您仍然可以一次解密1,280个字节。只需单独加密块。他们每个人都会得到填充物,并使其适合1,280。例如,一次加密1,279个字节(每个块都有一个1字节的填充。)用填充加密完整的1,280将给你1,296个字节(明文的16个字节的倍数将获得一个完整的16字节填充。 )

编辑,感兴趣:

如果你发现自己有一个大的密文,而你想要在块中解密它,并且由于某种原因你的解密受到约束,你被迫使用填充模式PKCS#7,你仍然可以解密数据块一次。它有点贵 - 它会花费你每块16字节的额外加密,但至少它是可能的。

取每个原始密文块,并为每个块加密一个16字节的小尾部,为该块正确填充。然后解密放大的块,最后,删除用于加密填充尾部的额外数据。

您只需将块的最后16个字节作为IV,并使用相同的密钥加密一些小数据 - 例如单个字节 - 用PKCS#7填充。将16字节加密结果附加到块,现在解密块+ 16字节。填充从尾部16个字节中删除,您可以删除数据位,最后得到原始的明文块。请参阅我的回复here