Связанные GZipStream / DeflateStream и CryptoStream (AES) разрываются при чтении

Я хочу сжать, а затем зашифровать свои данные, и для повышения скорости (за счет отсутствия необходимости записи в массивы байтов и обратно) решил объединить потоки, используемые для сжатия и шифрования, вместе.

Это работает. отлично, когда я пишу (сжимаю и шифрую) данные, но когда я пытаюсь прочитать данные (распаковывать и расшифровывать), операция чтения прерывается - простой вызов Read один раз читает ровно 0 байт, потому что первое чтение всегда возвращает 0. Цикл как в приведенном ниже коде почти работает, за исключением того, что в определенный момент Read перестает возвращать что-либо> 0, даже если есть еще данные для чтения.

Все, что до этих последних нескольких байтов, распаковывается и расшифровывается идеально.

Количество байты, оставшиеся, когда это происходит, остаются такими же для того же открытого текста; например, это всегда 9 байтов для одной строки, но всегда 1 байт для другой.

Ниже приводится соответствующий код шифрования и дешифрования; есть идеи относительно того, что может пойти не так?

Шифрование:

// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
    using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    using (DeflateStream zip = new DeflateStream(csEncrypt, CompressionMode.Compress, true))
    {
        zip.Write(stringBytes, 0, stringBytes.Length);
        csEncrypt.FlushFinalBlock();

Расшифровка:

// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream())
{
    // Writes the actual data (sans prepended headers) to the stream
    msDecrypt.Write(stringBytes, prependLength, stringBytes.Length - prependLength);
    // Reset position to prepare for read
    msDecrypt.Position = 0;
    // init buffer to read to
    byte[] buffer = new byte[originalSize];

    using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
    using (DeflateStream zip = new DeflateStream(csDecrypt, CompressionMode.Decompress))
    {
        // Hangs with "offset" at a small, deterministic number away from originalSize (I've gotten 9 less and 1 less for different strings)
        // Loop fixed as per advice
        int offset = 0;
        while (offset < originalSize)
        {
            int read = zip.Read(buffer, offset, originalSize - offset);
            if (read > 0)
                offset += read;
            else if (read < 0)
                Console.WriteLine(read); // Catch it if it happens.
        }
        // Hangs with "left" at a small, deterministic number (I've gotten 9 and 1 for different strings)
        /*
        for (int left = buffer.Length; left > 0; )
            left -= zip.Read(buffer, 0, left);
        */

Решение (Модификация шифрования):

// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
    using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    {
        using (DeflateStream zip = new DeflateStream(csEncrypt, CompressionMode.Compress, true))
            zip.Write(stringBytes, 0, stringBytes.Length);
        //Flush after DeflateStream is disposed.
        csEncrypt.FlushFinalBlock();
6
задан cervellous 23 July 2011 в 19:26
поделиться