Johny Wave
Johny Wave

Reputation: 141

Decrypt file into memory

I have function for decrypting files using Rijnadel (AES). Looks like this:

public static bool FileDecrypt(string inputFile, string outputFile, string password)
    {

        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        byte[] salt = new byte[32];

        FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
        fsCrypt.Read(salt, 0, salt.Length);

        RijndaelManaged AES = new RijndaelManaged();
        AES.KeySize = 256;
        AES.BlockSize = 128;
        var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Padding = PaddingMode.PKCS7;
        AES.Mode = CipherMode.CFB;

        CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);

        FileStream fsOut = new FileStream(outputFile, FileMode.Create);

            int read;
            byte[] buffer = new byte[1048576];

            try
            {
                while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
                    fsOut.Write(buffer, 0, read);
                }
            }
            catch (CryptographicException ex_CryptographicException)
            {
                fsOut.Close();
                fsCrypt.Close();
                LogWriter loger = new LogWriter("Cryptography error: " + ex_CryptographicException.ToString());
                return false;
            }
            catch (Exception ex)
            {
                fsOut.Close();
                fsCrypt.Close();
                LogWriter loger = new LogWriter("Exception error: " + ex.ToString());
                return false;
            }

            try
            {
                cs.Close();
            }
            catch (Exception ex)
            {
                fsCrypt.Close();
                fsOut.Close();
                LogWriter loger = new LogWriter("Error when closing Cryptostream. Error: " + ex.ToString());
                return false;
            }
            finally
            {
                fsOut.Close();
                fsCrypt.Close();
            }

    return true;


    }

It decrypts the file and creates new decrypted file.

But i would like to decrypt that file and load it only into memory. Mostly xml configuration files so then i would like to read the xml configuration with xmlserializer and use it in my program and then dispose the file from memory. Is that possible? Thanks for all answers.

PS: Dont mind closing of streams in all catches. Finally block didnt work for some reason, still trying to figure that out.

//EDIT:

This is my try:

MemoryStream inMemoryCopy = new MemoryStream();

        byte[] salt = new byte[32];
        using (FileStream fs = File.OpenRead(inputfile))
        {
            fs.Read(salt, 0, salt.Length);
            fs.CopyTo(inMemoryCopy);
        }

        byte[] bytesToBeDecrypted = inMemoryCopy.ToArray();
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);


        RijndaelManaged AES = new RijndaelManaged();
        AES.KeySize = 256;
        AES.BlockSize = 128;
        var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Padding = PaddingMode.PKCS7;
        AES.Mode = CipherMode.CFB;

        CryptoStream cs = new CryptoStream(bytesToBeDecrypted, AES.CreateDecryptor(), CryptoStreamMode.Read);

Problem is i cannot use byte array in cryptostream. And can i somehow do that even without filestream?

Upvotes: 1

Views: 1004

Answers (1)

Dbuggy
Dbuggy

Reputation: 911

You want to use XmlSerializer kinda like this to get some configuration object from stream. It doesn't matter wether the source stream is a FileStream, NetworkStream or even the CryptoStream itself. So there is no need to work with a byte buffer.

Note the following code is adapted from your code. I stripped the try catch from it to just only show the core code needed for the deserialization.

public SomeConfig ReadEncryptedConfiguration(string inputFile, string password)
{
    using (var stream = CreateStream(inputFile, password))
    {
        var ser = new XmlSerializer(typeof(SomeConfig));
        var config = (SomeConfig) ser.Deserialize(stream);
        return config;
    }
}

The CreateStream method will make the stream which is used and disposed in the previous part. I used another constructor to make sure that the underlying file stream is disposed when the CryptoStream is being disposed.

public CryptoStream CreateStream(string inputFile, string password)
{
    byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
    byte[] salt = new byte[32];

    FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
    fsCrypt.Read(salt, 0, salt.Length);

    RijndaelManaged AES = new RijndaelManaged();
    AES.KeySize = 256;
    AES.BlockSize = 128;
    var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
    AES.Key = key.GetBytes(AES.KeySize / 8);
    AES.IV = key.GetBytes(AES.BlockSize / 8);
    AES.Padding = PaddingMode.PKCS7;
    AES.Mode = CipherMode.CFB;

    return new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read, false);
}

Upvotes: 1

Related Questions