2

I want to to compress and encrypt a file in one go by using this simple code:

public void compress(FileInfo fi, Byte[] pKey, Byte[] pIV)
{
    // Get the stream of the source file.
    using (FileStream inFile = fi.OpenRead())
    {                
        // Create the compressed encrypted file.
        using (FileStream outFile = File.Create(fi.FullName + ".pebf"))
        {
            using (CryptoStream encrypt = new CryptoStream(outFile, Rijndael.Create().CreateEncryptor(pKey, pIV), CryptoStreamMode.Write))
            {
                using (DeflateStream cmprss = new DeflateStream(encrypt, CompressionLevel.Optimal))
                {
                    // Copy the source file into the compression stream.
                    inFile.CopyTo(cmprss);
                    Console.WriteLine("Compressed {0} from {1} to {2} bytes.", fi.Name, fi.Length.ToString(), outFile.Length.ToString());
                }
            }
        }
    }
}

The following lines will restore the encrypted and compressed file back to the original:

public void decompress(FileInfo fi, Byte[] pKey, Byte[] pIV)
{
    // Get the stream of the source file.
    using (FileStream inFile = fi.OpenRead())
    {
        // Get original file extension, for example "doc" from report.doc.gz.
        String curFile = fi.FullName;
        String origName = curFile.Remove(curFile.Length - fi.Extension.Length);

        // Create the decompressed file.
        using (FileStream outFile = File.Create(origName))
        {
            using (CryptoStream decrypt = new CryptoStream(inFile, Rijndael.Create().CreateDecryptor(pKey, pIV), CryptoStreamMode.Read))
            {
                using (DeflateStream dcmprss = new DeflateStream(decrypt, CompressionMode.Decompress))
                {                    
                    // Copy the uncompressed file into the output stream.
                    dcmprss.CopyTo(outFile);
                    Console.WriteLine("Decompressed: {0}", fi.Name);
                }
            }
        }
    }
}

This works also with GZipStream.

PePe
  • 65
  • 1
  • 6

1 Answers1

2

A decompressing stream is expected to be read from, not written to. (unlike a CryptoStream, which supports all four combinations of read/write and encrypt/decrypt)

You should create the DeflateStream around a CryptoStreamMode.Read stream around the input file, then copy from that directly to the output stream.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • @zaqk: Please update your question with the corrected code so that the first mistake isn't muddling things up. – EricLaw Dec 01 '14 at 18:41
  • @zaqk: You need to make the CryptoStream read from the input stream, not write to the output stream. – SLaks Dec 01 '14 at 18:42
  • @zaqk: That's completely wrong. You need to create both streams around eachother and the **input** file, then copy directly to the output stream. – SLaks Dec 01 '14 at 18:54
  • 1
    https://github.com/ShomreiTorah/Libraries/blob/master/ShomreiTorah.Common/Updates/UpdateFile.cs#L139-L145 – SLaks Dec 01 '14 at 19:09