【问题标题】:Padding is invalid and cannot be removed exception and length of the data to decrypt is invalid. Rijndael填充无效且无法删除异常和要解密的数据长度无效。里金达尔
【发布时间】:2018-02-26 23:18:19
【问题描述】:

我的要求如下。 步骤 1)我想通过以 10-10 MB 的块加密来在本地文件系统中写入 101 MB 的数据。

第 2 步)解密时,我想从文件中获取 10-10 MB 的数据并想解密并希望将 10-10 MB 解密后的数据传递给其他函数(注意:我的最后一个块大小为 1 MB文件大小为 101 MB)。

所以

1) 当我尝试仅解密 10 MB 时,会出现错误“填充无效且无法删除”

2) 现在,在解密时,如果我将 paddingMode 设置为 None,那么当最后一个块出现时,即 1 MB,它会给出错误“要解密的数据长度无效”。高达 100 MB 的东西正在运行

注意: 1) 多达 100 MB 的内容按预期工作。如果我给最后一个块大小 10 MB 而不是 1 MB 那么它的工作但最后我的目标文件大小将是 110 MB 而不是 101 MB。 2)我在加密时没有给出填充模式,而是为了避免填充无效错误,而在解密时我没有给出它。暂时我已经评论了该代码。

3) 我使用相同的密钥和 IV 进行加密和解密

加密代码:

private void WriteStreamInChunks(Stream fsstream, string filePath)
    {   
        int chunkSize = 10 * 1024 * 1024;
        byte[] buffer = new byte[chunkSize];

        using (var rijndaelManaged = new RijndaelManaged())
        {
            var encryptor = rijndaelManaged.CreateEncryptor(EncryptionKey, EncryptionIV);

            using (var fileStream = File.Create(filePath))
            {
                using (var cryptoStream = new CryptoStream(fileStream, encryptor, CryptoStreamMode.Write))
                {
                    int bytesRead;
                    while ((bytesRead = fsstream.Read(buffer, 0, chunkSize)) > 0)
                    {
                        cryptoStream.Write(buffer, 0, bytesRead);
                    }

                    if (!cryptoStream.HasFlushedFinalBlock)
                        cryptoStream.FlushFinalBlock();
                }
            }
        }
    }

仅解密块并返回 byte[] 代码 - 错误

“填充无效”如果我将填充模式设置为零然后数据长度无效异常。

public byte[] GetDecryptedFileContent(string filePath, long chunkSizeInBytes, long seekValue, long fileSize, string encryptionIV)
    {
        var sourceFile = new FileInfo(filePath);
        var buffer = new byte[chunkSizeInBytes];

        byte[] encryptionKey = File.ReadAllBytes(Utils.GetSymmetricAlgoEncryptionKey());

        using (var fileStream = File.Open(sourceFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            fileStream.Seek(seekValue, SeekOrigin.Begin);
            using (var binaryReader = new BinaryReader(fileStream))
            {
                binaryReader.Read(buffer, 0, buffer.Length);
            }
        }

        using (MemoryStream dataOut = new MemoryStream())
        {
            using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
            {
                //rijndaelManaged.Padding = PaddingMode.None;

                ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(encryptionKey, Convert.FromBase64String(encryptionIV));

                using (CryptoStream cryptoStream = new CryptoStream(dataOut, decryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(buffer, 0, buffer.Length);
                    return dataOut.ToArray();
                }
            }
        }
        return null;
    }

根据我的要求,我必须从这个 GetDecryptedFileContent 函数返回 byte[]。 我多次调用此函数,直到文件大小变为 0。即对于每个块。 enter code here 有人可以帮帮我吗?

我只想返回 10-10 MB。

【问题讨论】:

    标签: chunking rijndaelmanaged cryptostream


    【解决方案1】:

    输入必须是块大小的倍数,否则必须使用填充。填充仅添加到加密的最后一个块。见PKCS#7 padding

    如果一次读取文件的一部分,请确保块大小是块大小的倍数。在读取时,为文件的最后一个块以外的所有块指定不填充,并为文件的最后一个块指定填充。

    更新:您使用的是 CBC 模式,因为您使用的是 IV。在这种情况下,对于第一个块之外的所有块,IV 将是前一个块。只需阅读前一个块并将其用于 IV。见CBC mode

    【讨论】:

    • 感谢您的回复。
    • 感谢您的回复。我在这里要做的是 1)我一次性加密所有内容并将其写入文件。 2)我想解密文件,例如如果文件大小为 101 MB,块大小为 20 MB,则 20-20 MB 我想解密,无论数据被解密,我都想返回它。
    猜你喜欢
    • 2011-12-25
    • 1970-01-01
    • 2021-03-15
    • 2010-09-23
    • 2017-07-26
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多