崩溃与"填充无效,无法删除"当CryptoStream关闭时

时间:2017-07-18 13:36:54

标签: c# encryption windows-mobile

tl; dr 加密和解密工作正常且正确。我查了一切。当我从CryptoStream读取整个内容时,会出现问题。我使用RijndaelManaged类,该应用程序适用于Windows Mobile 6。

此应用程序适用于XML,它必须加密写入磁盘的所有内容。获得XML(在内存中)后,它会将内容直接加密到文件中。之后,应用程序必须将所有这些小型XML组合成一个大型XML,但与此同时,我们可能需要XML中的一些信息。为了优化内存使用,我没有将整个XML加载到内存中,我使用XmlReader只从CryptoStream读取它所需要的内容。但这与" Padding崩溃无效,无法删除"

例如,这非常有效:

using (var fileStream = new FileStream(ResponsePath, FileMode.Open))
using (var crpytoStream = new CryptoStream(fileStream, key.CreateDecryptor(), CryptoStreamMode.Read))
using (var reader = StreamReader.Create(crpytoStream, settings))
{
    reader.ReadToEnd();
}

而这不是:

using (var fileStream = new FileStream(ResponsePath, FileMode.Open))
using (var crpytoStream = new CryptoStream(fileStream, key.CreateDecryptor(), CryptoStreamMode.Read))
using (var reader = StreamReader.Create(crpytoStream, settings))
{
    var buffer = new char[1024];
    reader.ReadBlock(buffer , 0, 1024);
}

我有一个解决方案,但它看起来像一个可怕的黑客,它对巨大的XML并不好。如果您了解更清洁的解决方案,我感谢您

编辑: 我测试了从流中读取不同数量的字节。

  • 如果我从0开始读取1,2,3,...或1024字节,则在关闭流时会崩溃。
  • 如果我从0开始并读取1025,1026,1027,...或2048字节,则关闭流时不会崩溃。
  • 如果我从0开始读取2049,2050,...或4096字节,它将崩溃 当我关闭流时。
  • 如果我从0开始读取4097字节,则关闭流时不会崩溃。
  • 如果我从0开始读取8192个字节,它将崩溃 当我关闭流时。

在阅读之前加载IV。

2 个答案:

答案 0 :(得分:0)

解决方案是创建另一个流来读到最后。在我从XML获取所需的所有数据后,我创建了一个StreamReader并阅读了所有内容。如果XML是巨大的,这显然是不好的。

using (var workaroundStream = new StreamReader(crpytoStream))
{
    var workaroundBuffer = new char[1024];
    while (workaroundStream.ReadBlock(workaroundBuffer, 0, 1024) != 0)
    {
    }
}

答案 1 :(得分:0)

可以从加密数据的中间读取和解密。

  1. 开始读取块边界,16字节用于AES。
  2. 停止读取任何块bounbdry。
  3. 读取块大小的倍数。
  4. 解密,没有填充。
  5. 注意:

    • 如果模式是CBC,则先读取一个块,然后将其用作IV。
    • 如果读到最后用填充解密。

    AES是一种基于块的加密算法,它一次处理一个块。因此,只要起始点位于加密期间使用的块边界上并且长度是块大小的倍数,就可以从开头以外开始解密。

    对于CBC模式,先前的块与加密前的数据相关,并且在解密时必须再次与解密的数据进行对比。请参阅CBC mode

    请参阅PKCS#7 padding