Marius Popa
Marius Popa

Reputation: 584

RijndaelManaged - Encrypt/Decrypt a Stream in C#

I am trying to encrypt and decrypt a stream (a PDF document at base), but I am having issues with this. When I try to open the document after decryption and download, I get the error Failed to load the PDF document.

Do you know why this might be happening?

Here is the code for encryption:

public EncryptResult EncryptStream(Stream dataStream, bool reuseIV = false)
    {
        RijndaelManaged crypto = new RijndaelManaged();
        crypto.Key = _key;

        if (!reuseIV || _iv == null)
        {
            // make a copy of the current IV
            _iv = crypto.IV;
        }
        else
        {
            // reuse the previous IV
            crypto.IV = _iv;
        }

        var result = new EncryptResult() { IV = crypto.IV };

        using (var encryptor = crypto.CreateEncryptor())
        {
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
               {
                    var byteArrayInput = new byte[dataStream.Length];
                    dataStream.Read(byteArrayInput, 0, byteArrayInput.Length);
                    csEncrypt.Write(byteArrayInput, 0, byteArrayInput.Length);
                    dataStream.Close();

                    result.Cipher = msEncrypt.ToArray();

                    msEncrypt.Flush();
                    msEncrypt.Position = 0;

                    return result;
                }
            }
        }
    }

and decryption:

public Stream DecryptStream(byte[] cipher, byte[] iv)
    {
        RijndaelManaged crypto = new RijndaelManaged();
        crypto.Key = _key;
        crypto.IV = iv;

        crypto.Padding = PaddingMode.Zeros;

        using (var decryptor = crypto.CreateDecryptor())
        {
            using (MemoryStream msDecrypt = new MemoryStream(cipher))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    var sOutputFilename = new MemoryStream();
                    var fsDecrypted = new StreamWriter(sOutputFilename);
                    fsDecrypted.Write(new StreamReader(csDecrypt).ReadToEnd());

                    sOutputFilename.Position = 0;
                    return sOutputFilename;
                }
            }
        }
    }

Thanks in advance.

Upvotes: 2

Views: 1734

Answers (2)

bommelding
bommelding

Reputation: 3037

using (MemoryStream msEncrypt = new MemoryStream())
{
   using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
   {
        //var byteArrayInput = new byte[dataStream.Length];
        //dataStream.Read(byteArrayInput, 0, byteArrayInput.Length);
        //csEncrypt.Write(byteArrayInput, 0, byteArrayInput.Length);
        dataStream.CopyTo(csEncrypt);
        dataStream.Close();

        //result.Cipher = msEncrypt.ToArray();  // not here - not flushed yet
        //msEncrypt.Flush();                    // don't need this
        //msEncrypt.Position = 0;            
    }
    result.Cipher = msEncrypt.ToArray();  
    return result;
}

and in the decryptor, get rid of all the StreamReader/StreamWriter stuff. A PDF file is compressed, ie binary. But this is after the decryption so it can't be your error.

using (var decryptor = crypto.CreateDecryptor())
{
    using (MemoryStream msDecrypt = new MemoryStream(cipher))
    {
       var outputStream = new MemoryStream();

        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {               
            csDecrypt.CopyTo(outputStream );
        }
        outputStream .Position = 0;
        return outputStream ;
    }
}

Upvotes: 1

TheGeneral
TheGeneral

Reputation: 81493

One issue is, you are likely encrypting excess bytes at the end of your stream, you need to work out how many bytes are read or use

Stream.CopyTo Method

Reads the bytes from the current stream and writes them to another stream.

Upvotes: 0

Related Questions