为什么我的解密只有在我之前在同一个程序中直接加密才有效?

时间:2010-07-18 21:48:29

标签: c# encryption aes

我从MSDN获得了这个例子。我想知道为什么如果我注释掉Rijndael EncryptTextToFile()函数它不会解密所有文本文件。

一些很好的例子也会受到欢迎,因为我不确定如何将其设置为256位和CBC模式。

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 个答案:

答案 0 :(得分:2)

RijndaelAlg.IV似乎永远不会被初始化。也许C#例程在没有提供时提供全零IV,但也许不提供。也许它随机选择一个IV,并且当加密和解密行都存在时,你的代码工作的唯一原因是因为你的代码依赖于一个永远不会存储的随机IV。 (这对我来说纯粹是猜测。)

作为一个更大的'风格'问题,我发现第一个Rijndael对象仅用于将其一些成员传递给另一个例程有点奇怪;在其他例程中,创建了一个全新的Rijndael对象。您的程序正在创建三个不同的Rijndael上下文,并且只使用其中两个。第三种方法仅用于保留预处理密钥和IV(未经本代码初始化使用)。

答案 1 :(得分:2)

sarnold在所有方面都是正确的,这是一个改进的代码示例。它与前一个有点不同:

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();
        }
    }
}