windows phone 8-C#AesManaged异常:填充无效,无法删除

本文关键字:删除 无效 填充 phone 8-C#AesManaged 异常 windows | 更新日期: 2023-09-27 17:57:33

我知道有很多这样的问题有答案,但我花了很多小时在谷歌上搜索,并尝试了我找到的所有建议。

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

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

当程序到达这一行时:decodeContent=r.ReadBytes(encodeContent.Length) 我得到CryptographicException,并显示以下消息:填充无效,无法删除

有人能帮我解决这个问题吗?

windows phone 8-C#AesManaged异常:填充无效,无法删除

您无法按块解密,因为silverlight AesManaged总是包含填充,并且如果您只读取加密块的一部分,则解密类找不到应该删除的填充。您只能解密整个数据。或者,您可以在算法的加密部分手动拆分数据。Hans Passant也告诉过你,只是简短地说了一句;)

如果在最后一个块之前不删除填充进行解密,则一次可以解密1280个字节。也就是说,您必须将解密器设置为,而不是删除除最后一个块之外的所有块上的填充(即"无填充")。

即当有N个区块时:

  • 对于块1到N-1:解密(1280字节,无填充)
  • 对于块N:解密(无论剩余多少字节,填充)

您也可以在"无填充"的情况下运行整个解密过程,并自己去掉填充。最后一个字节将提供从末尾截取的字节数,从1到16。

如果你不能在解密时关闭填充删除(上面的评论暗示了这一点),你仍然可以一次解密1280个字节。只需单独加密块即可。他们每个人都会得到填充物,使其适合1280。例如,一次加密1279个字节(每个块都有一个1字节的填充。)用填充加密整个1280将得到1296个字节(16字节明文的倍数将得到一个完整的16字节填充。)

编辑,为感兴趣的:

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

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

您只需将块的最后16个字节作为IV,并使用相同的密钥加密一些小数据——例如一个字节——填充PKCS#7。将16字节的加密结果附加到块,现在解密块+16字节。填充是从尾部16字节中删除的,您可以删除数据位,最终得到原始的明文块。在我的回答中查看更多信息