tags:

views:

108

answers:

2

I got this example from msdn and what wondering why it wont decrypt all the text file if I comment out the Rijndael EncryptTextToFile() function.

Some good examples would be welcome as I am unsure how to set to 256bit and CBC mode.

Thanks

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RijndaelSample
{

    static void Main()
    {
        try
        {
            // Create a new Rijndael object to generate a key
            // and initialization vector (IV).
            Rijndael RijndaelAlg = Rijndael.Create();

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            string privateKey = "qwertyuiopasdfghjklzxcvbnmqwerty";
            RijndaelAlg.Key = encoding.GetBytes(privateKey);

            // Create a string to encrypt.
            string sData = "Here is some data to encrypt cookiejar.";
            string FileName = "CText.txt";

            // Encrypt text to a file using the file name, key, and IV.
            EncryptTextToFile(sData, FileName, RijndaelAlg.Key, RijndaelAlg.IV);

            // Decrypt the text from a file using the file name, key, and IV.
            string Final = DecryptTextFromFile(FileName, RijndaelAlg.Key, RijndaelAlg.IV);

            // Display the decrypted string to the console.
            Console.WriteLine(Final);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        Console.ReadLine();
    }

    public static void EncryptTextToFile(String Data, String FileName, byte[] Key, byte[] IV)
    {
        try
        {
            // Create or open the specified file.
            FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

            // Create a new Rijndael object.
            Rijndael RijndaelAlg = Rijndael.Create();

            // Create a CryptoStream using the FileStream 
            // and the passed key and initialization vector (IV).
            CryptoStream cStream = new CryptoStream(fStream,
                RijndaelAlg.CreateEncryptor(Key, IV),
                CryptoStreamMode.Write);

            // Create a StreamWriter using the CryptoStream.
            StreamWriter sWriter = new StreamWriter(cStream);

            try
            {
                // Write the data to the stream 
                // to encrypt it.
                sWriter.WriteLine(Data);
            }
            catch (Exception e)
            {
                Console.WriteLine("An error occurred: {0}", e.Message);
            }
            finally
            {
                // Close the streams and
                // close the file.
                sWriter.Close();
                cStream.Close();
                fStream.Close();
            }
        }
        catch (CryptographicException e)
        {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine("A file error occurred: {0}", e.Message);
        }

    }

    public static string DecryptTextFromFile(String FileName, byte[] Key, byte[] IV)
    {
        try
        {
            // Create or open the specified file. 
            FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

            // Create a new Rijndael object.
            Rijndael RijndaelAlg = Rijndael.Create();

            // Create a CryptoStream using the FileStream 
            // and the passed key and initialization vector (IV).
            CryptoStream cStream = new CryptoStream(fStream,
                RijndaelAlg.CreateDecryptor(Key, IV),
                CryptoStreamMode.Read);

            // Create a StreamReader using the CryptoStream.
            StreamReader sReader = new StreamReader(cStream);

            string val = null;

            try
            {
                // Read the data from the stream 
                // to decrypt it.
                val = sReader.ReadLine();


            }
            catch (Exception e)
            {
                Console.WriteLine("An error occurred: {0}", e.Message);
            }
            finally
            {

                // Close the streams and
                // close the file.
                sReader.Close();
                cStream.Close();
                fStream.Close();
            }

            // Return the string. 
            return val;
        }
        catch (CryptographicException e)
        {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            return null;
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine("A file error occurred: {0}", e.Message);
            return null;
        }
    } 
}
+2  A: 

RijndaelAlg.IV never appears to be initialized. Perhaps the C# routines provide for an all-zero IV when none is provided, but perhaps not. Perhaps it picks an IV at random, and the only reason your code works when both the encrypt and decrypt lines are present is because your code is relying on a random IV that is never stored. (This is pure guesswork on my part.)

As a larger 'style' issue, I find it a little strange that the first Rijndael object is used just to pass some of its members to another routine; within that other routine an entirely new Rijndael object is created. Your program is creating three different Rijndael contexts, and only two of them are ever used. The third exists solely for holding onto pre-processed key and IV (which is used without being initialized by this code).

sarnold
+2  A: 

sarnold is correct on all counts, here is an improved code sample. It works a little differently than the previous one:

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RijndaelSample
{
    const String CryptFile = "Crypt.dat";
    const String IVFile = "IV.dat";

    static void Main()
    {
        try
        {
            // Create a new Rijndael object to generate a key
            // and initialization vector (IV).
            Rijndael RijndaelAlg = Rijndael.Create();

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            string privateKey = "qwertyuiopasdfghjklzxcvbnmqwerty";
            RijndaelAlg.Key = encoding.GetBytes(privateKey);

            bool cryptFileExists = File.Exists(CryptFile);
            bool ivFileExists = File.Exists(IVFile);
            if (cryptFileExists && ivFileExists)
            {
                Console.WriteLine("Enter Text to Encrypt, or a Blank Line to Decrypt Previous:");
            }
            else
            {
                Console.WriteLine("Enter Text to Encrypt:");
            }

            // Create a string to encrypt.
            string sData = Console.ReadLine();

            if (!String.IsNullOrEmpty(sData))
            {
                // Initialize the IV explicitly to something random
                RijndaelAlg.GenerateIV();
                // Encrypt text to a file using the file name, key, and IV.
                EncryptTextToFile(sData, CryptFile, RijndaelAlg);
                // Save the IV for use when decrypting
                File.WriteAllBytes(IVFile, RijndaelAlg.IV);
            }
            else if (!cryptFileExists || !ivFileExists)
            {
                throw new InvalidOperationException("Previous Encrypted Data Not Found");
            }
            else
            {
                // Read the IV that was used for encrypting the file
                RijndaelAlg.IV = File.ReadAllBytes(IVFile);
            }

            // Decrypt the text from a file using the file name, key, and IV.
            string Final = DecryptTextFromFile(CryptFile, RijndaelAlg);

            // Display the decrypted string to the console.
            Console.WriteLine(Final);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        Console.ReadLine();
    }

    public static void EncryptTextToFile(String Data, String FileName, Rijndael rij)
    {
        // Create or open the specified file.
        using (FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate, FileAccess.Write))
        // Create a CryptoStream using the FileStream 
        // and the passed key and initialization vector (IV).
        using (CryptoStream cStream = new CryptoStream(fStream, rij.CreateEncryptor(), CryptoStreamMode.Write))
        // Create a StreamWriter using the CryptoStream.
        using (StreamWriter sWriter = new StreamWriter(cStream))
        {
            // Write the data to the stream 
            // to encrypt it.
            sWriter.WriteLine(Data);
        }
    }

    public static string DecryptTextFromFile(String FileName, Rijndael rij)
    {
        // Open the specified file.
        using (FileStream fStream = File.Open(FileName, FileMode.Open, FileAccess.Read))
        // Create a CryptoStream using the FileStream 
        // and the passed key and initialization vector (IV).
        using (CryptoStream cStream = new CryptoStream(fStream, rij.CreateDecryptor(), CryptoStreamMode.Read))
        // Create a StreamReader using the CryptoStream.
        using (StreamReader sReader = new StreamReader(cStream))
        {
            // Read the data from the stream 
            // to decrypt it.
            return sReader.ReadToEnd();
        }
    }
}
Paul Wh
Looks like a very nice improvement over the original code.
sarnold