0

私の要件は以下のようなものです。ステップ 1) ローカル ファイル システムに 101 MB のデータを書き込み、10 ~ 10 MB のチャンクで暗号化します。

ステップ 2) 復号化中に、ファイルから 10 ~ 10 MB のデータを取得し、復号化して、復号化した 10 ~ 10 MB を他の関数に渡したい (注: ファイル サイズが 1 MB であるため、最後のチャンク サイズは 1 MB になります) 101MB)。

そう

1) 10 MB のみを復号化しようとすると、「パディングが無効であり、削除できません」というエラーが表示されます

2) さて、復号化中に paddingMode を None にすると、最後のチャンク、つまり 1 MB になると、「復号化するデータの長さが無効です」というエラーが発生します。最大 100 MB のものが機能しています

注: 1) 100 MB までは期待どおりに動作しています。最後のチャンク サイズを 1 MB ではなく 10 MB にすると動作しますが、最終的に目標ファイル サイズは 101 MB ではなく 110 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 だけを返したい。

4

1 に答える 1

0

入力はブロック サイズの倍数であるか、パディングを使用する必要があります。パディングは、暗号化された最後のブロックにのみ追加されます。PKCS#7 パディングを参照してください。

一度にファイルの一部を読み取る場合は、チャンク サイズがブロック サイズの倍数であることを確認してください。読み取り時に、ファイルの最後のブロックを除くすべてのブロックにパディングを指定せず、ファイルの最後のブロックにパディングを指定します。

更新: IV を使用しているため、CBC モードを使用しているようです。その場合、最初のブロックを超えるすべてのブロックで、IV は前のブロックになります。前のブロックを読んで IV に使用するだけです。CBC モードを参照してください。

于 2017-09-18T13:35:15.403 に答える