0

I have two methods, one works, the other not. Working method:

public static void CompressAndEncrypt(string sourceFile, string encrFile)
{
  int bufferSize = 5242880;
  using (var readStream = new FileStream(sourceFile, FileMode.Open, FileAccess.ReadWrite))
  {
    using (var writeStream = new FileStream(encrFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
    {
      DESCryptoServiceProvider cryptic = new DESCryptoServiceProvider();
      cryptic.Key = ASCIIEncoding.ASCII.GetBytes("ABCDEFGH");
      cryptic.IV = ASCIIEncoding.ASCII.GetBytes("ABCDEFGH");
      using (var crypto = new CryptoStream(writeStream, cryptic.CreateEncryptor(), CryptoStreamMode.Write))
      {
        using (var zip = new GZipStream(crypto, CompressionMode.Compress))
        {
          int bytesRead = -1;
          byte[] bytes = new byte[bufferSize];

          while ((bytesRead = readStream.Read(bytes, 0, bufferSize)) > 0)
          {
            zip.Write(bytes, 0, bytesRead);
          }
        }
      }
    }
  }
}

Nonworking method:

public static void CompressAndEncryptBlock(string sourceFile, string outputFile)
{
  int bufferSize = 5242880;
  int bytesRead;
  var bytes = new byte[bufferSize];

  using (var readStream = new FileStream(sourceFile, FileMode.Open, FileAccess.ReadWrite))
  {
    using (var writer = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
    {
      while ((bytesRead = readStream.Read(bytes, 0, bufferSize)) > 0)
      {
        using (var writeStream = new MemoryStream())
        {
          DESCryptoServiceProvider cryptic = new DESCryptoServiceProvider();
          cryptic.Key = Encoding.ASCII.GetBytes("ABCDEFGH");
          cryptic.IV = Encoding.ASCII.GetBytes("ABCDEFGH");
          using (var crypto = new CryptoStream(writeStream, cryptic.CreateEncryptor(), CryptoStreamMode.Write))
          {
            using (var zip = new GZipStream(crypto, CompressionMode.Compress, true))
            {
              zip.Write(bytes, 0, bytesRead);
              //After that, the Capacity of writeStream (MemoryStream) is somehow greater than its Length
            }
            var bytes1 = new byte[writeStream.Length];
            writeStream.Read(bytes1, 0, bytes1.Length);
            writer.Write(bytes1, 0, bytes1.Length);
          }
        }
      }
    }
  }
}

Why does the second processing of the file go wrong? The second way I will need in the future is to transfer the file in blocks (now while I'm just testing it for writing to disk). After using the second method, the file size is slightly smaller than when using the first method. And further, if I decrypt and decompress I get this exception:

System.IO.InvalidDataException occurred
  HResult=0x80131501
  Message=Invalid magic number in the GZip header. The transfer must go to the GZip stream.
  Source=System
  StackTrace:
   at System.IO.Compression.GZipDecoder.ReadHeader(InputBuffer input)
   at System.IO.Compression.Inflater.Decode()
   at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
   at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
   at System.IO.Compression.GZipStream.Read(Byte[] array, Int32 offset, Int32 count)

If I use the first method I can decrypt and decompress (I use only one method for decrypt and decompress).

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
NIk Pos
  • 1
  • 2
  • How does the second one go wrong? Does it not compile? Does it throw an exception? Does it complete without errors but not actually seem to have done what you expected? Something else? Please be more specific with the nature of your error so we know where to focus our attention - full error message of exception along with what line it is on is the minimum you should be giving us. Or if there is no exception an exact description of what you expect to happen and what did in fact happen. – Chris Sep 25 '17 at 08:37
  • 3
    Well in the second one you keep opening and closing the streams, essentially creating small portions (basically "sub-streams") that are encrypted and zipped. The result **can't** be the same because of the header/padding/etc. that comes with streams like that. You can't just *pause* and *resume* compression / encryption like that, your streams are in completely different states. – Manfred Radlwimmer Sep 25 '17 at 08:40
  • I corrected the description of the question – NIk Pos Sep 25 '17 at 08:46
  • @NIkPos The problem is still the same. The problem is not simply a small syntax error or mistake, it is in the basic design concept of your method. If you want to transmit the compressed and encrypted file in chunks, you have to either store it first, transmit it during encryption/compression or handle the decryption differently. You can't just encrypt different parts of a file on-the-fly and expect the result to be the same. Compression and encryption are not stateless actions that can be performed without knowledge of what happened before. – Manfred Radlwimmer Sep 25 '17 at 08:51
  • @ManfredRadlwimmer I have to send chunks after zip.Write(bytes, 0, bytesRead)? – NIk Pos Sep 25 '17 at 10:08
  • That depends on how you actually send the chunks. If you send them via Tcp for example you could just replace the `writeStream` with a Tcp Stream. – Manfred Radlwimmer Sep 25 '17 at 10:09
  • @ManfredRadlwimmer I will send to the cloud storage. – NIk Pos Sep 25 '17 at 10:19
  • Is the encryption / compression a requirement of the cloud api or is that just how you want to store the file online? – Manfred Radlwimmer Sep 25 '17 at 10:22
  • @ManfredRadlwimmer I want to perform file processing on the client side and save the processed file on the cloud storage. – NIk Pos Sep 25 '17 at 10:27
  • That doesn't really answer my question, but maybe this gives you an idea: https://stackoverflow.com/questions/5090233/how-to-encrpyt-decrypt-data-in-chunks – Manfred Radlwimmer Sep 25 '17 at 10:29

0 Answers0