Subclass StreamReader to create a decrypt File stream Reader
Asked Answered
M

1

6

I am trying to create a decrypted File stream reader (DFSR) class by subclassing StreamReader so I can pass the filename with encrpyted info to its (DFSR) constructor and return with the streamReader that I can call upon ReadLine method of StreamReader.

I know how to do it as below, but I do not know how to refractor it into a class with StreamReader as parent class.

using (Rijndael rijAlg = Rijndael.Create())
{
    rijAlg.Key = DX_KEY_32;
    rijAlg.IV = DX_IV_16;

    // Create a decrytor to perform the stream transform.
    using (FileStream fs = File.Open("test.crypt", FileMode.Open))
    {
        using (CryptoStream cs = new CryptoStream(fs, rijAlg.CreateDecryptor(), CryptoStreamMode.Read))
        {
            using (StreamReader sr = new StreamReader(cs))
            {
                string line;
                // Read and display lines from the file until the end of  
                // the file is reached. 
                while ((line = sr.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }

        }
    }

}
Melanochroi answered 4/7, 2013 at 18:47 Comment(2)
That would be a misuse of inheritance. What you should do is to just use the regular StreamReader, but properly initialized to use a CryptoStream. Basically, just like your code is structured right now. You can put all of that into a helper method. Inheritance adds no value here. If you insist on inheriting from something, inherit from TextReader and wrap a properly initialized StreamReader.Jeff
Agree with @Jeff that you should be using System.Security.Cryptography.CryptoStream as it already inherits from System.IO.Stream.Promote
M
0

You can use a static method from the constructor to generate the crypto stream similar to the following:

public class EncryptingFileStream : System.IO.StreamReader
{

    public EncryptingFileStream(string fileName, byte[] key, byte[] IV)
        : base(GenerateCryptoStream(fileName, key, IV))
    {
    }

    private static System.IO.Stream GenerateCryptoStream(string fileName, byte[] key, byte[] IV)
    {

        using (System.Security.Cryptography.Rijndael rijAlg = System.Security.Cryptography.Rijndael.Create())
        {
            rijAlg.Key = key;
            rijAlg.IV = IV;

            // Create a decrytor to perform the stream transform.
            using (System.IO.FileStream fs = System.IO.File.Open(fileName, System.IO.FileMode.Open))
            {
                return new System.Security.Cryptography.CryptoStream(fs, rijAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
            }
        }
    }
}

To use this class:

        using (EncryptingFileStream fs = new EncryptingFileStream("test.crypt", DX_KEY_32, DX_IV_16))
        {
            string line;
            // Read and display lines from the file until the end of  
            // the file is reached. 
            while ((line = fs.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
Monometallism answered 4/7, 2013 at 19:4 Comment(7)
The using statement is closing the file stream. It needs to remain open for the lifetime of the reader.Atrip
It make sense to remove 'using', Does that mean we will have to declare 'rijAlg' and 'fs' statics. If I make 'fs' static, does that mean all instance of this class is restricted to a single file called 'filename'Melanochroi
@IreneLee: the only thing that needs to be static is the method itself. Any parameters passed to the method would be instance, non-static values, so you can call it with whatever file names you like.Monometallism
@IreneLee: I updated the answer to show how the class would be used.Monometallism
How do I destroy CryptoStream instance in my destructor. Or do I need to do that?Melanochroi
@IreneLee: you shouldn't need to do that, but if you do, you can get at it using the BaseStream property of the EncryptingFileStream.Monometallism
I try to copy the above code and test it. I got the problem - 'Can not access the closed file' using (EncryptingFileStream wr = new EncryptingFileStream("test2.crypt")) { for (int i = 0; i < 10; i++) { wr.WriteLine("The Y number is Y" + i.ToString()); } }Melanochroi

© 2022 - 2024 — McMap. All rights reserved.