I am following the MSDN Example of Rijndael Encryption, only that I would like to encrypt and return a stream.
The following does not work.
It throws no exception but after stepping through the code, the return value has no data.
public static Stream EncryptStream(Stream plainStream, byte[] Key, byte[] IV)
{
var encrypted = new MemoryStream()
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainStream);
}
msEncrypt.CopyTo(encrypted);
}
}
}
return encrypted;
}
I looked at the documentation for the Stream.Writer class, thinking that it has something to do with it not supporting writing to a Stream.
I noticed that there is an 'object' type parameter, so I am assuming it would work... Is that correct? If not, how do I do it?
I pass a FileStream to it, by the way. Stepping through the code, plainStream does contain data.
Here are some sample function to encrypt and decrypt from and to streams (replace the algo by the one you prefer):
public static void Decrypt(Stream input, Stream output, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) // Creates the default implementation, which is RijndaelManaged.
{
using (CryptoStream stream = new CryptoStream(input, algo.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
byte[] bytes = new byte[16];
int read;
do
{
read = stream.Read(bytes, 0, bytes.Length);
output.Write(bytes, 0, read);
}
while (read > 0);
}
}
}
public static void Encrypt(Stream input, Stream output, byte[] key, byte[] iv)
{
using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) //Creates the default implementation, which is RijndaelManaged.
{
using (CryptoStream stream = new CryptoStream(output, algo.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] bytes = new byte[16];
int read;
do
{
read = input.Read(bytes, 0, bytes.Length);
stream.Write(bytes, 0, read);
}
while (read > 0);
}
}
}
You can use them with any output stream. If you want to write to a large output stream, you can use that output stream directly (for example a FileStream or ASP.NET Response.OutputStream, etc.), you should not use an intermediary MemoryStream which will consume memory for no real purpose.
That being said, if you really want to use a MemoryStream, you would do it like this:
MemoryStream output = new MemoryStream();
Encrypt(input, output, key, iv);
output.Position = 0; // rewind the stream, so you can use it from the beginning