C#中的AES加密并比较文件级别的结果

AES encryption in c# and compare result in file level

AES 的新手,我访问了几个关于它的线程,例如:Dan Esparza 的例子,Zeeshan Amber 在这个线程 Simple encryption algorithm in c#.net , and smdrager at Simple encryption algorithm in c#.net

我尝试在我的案例中使用一些例子,但我发现了一些不正确的地方,让我解释一下:

  1. 我想加密一个二进制文件(名为 "exa" )。
  2. 我使用 git 检查输出文件是否与输入文件不同。
  3. 我将输入文件读取到流(字节[]或字符串)。
  4. 紧接着,立即使用 File.WriteAllBytes() 写入不同的文件。 (确保读取字节正确,成功
  5. 然后,我用了 Dan Esparza、smdrager、Zeeshan Amber 的例子
  6. 每次完成后,我都会将内存中的解密字节与原始字节进行比较,看字节是否不同。
  7. 我把解密结果保存到文件里比较了。
  8. 结果都令人失望,所有文件都失败了,但在某些情况下字节比较没问题。

smdrager的例子

byte[] orgBytes = File.ReadAllBytes("exa");

byte[] encQuote = EncryptByteToBytes(orgBytes , "password" );
byte[] endByte = DecryptToByte(encQuote, "password");

File.WriteAllBytes("exaOutputBytes", endByte);

字节数比较失败,文件比较也失败

orgBytes.Length : 55732
endByte.Length : 55744

Dan Esparza 的例子

在这种情况下,字节输入将失败,因此,我使用 ASCII 文本读取。

        string original = File.ReadAllText("exa" , Encoding.ASCII );

        using (RijndaelManaged myRijndael = new RijndaelManaged())
        {

            myRijndael.GenerateKey();
            myRijndael.GenerateIV();
            // Encrypt the string to an array of bytes. 
            byte[] encrypted = EncryptStringToBytes(original, myRijndael.Key, myRijndael.IV);

            // Decrypt the bytes to a string. 
            string roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);

            File.WriteAllText("exaOutputString", roundtrip , Encoding.ASCII);

字节比较很好,无论是长度还是每个字节的内容。但是文件比较还是失败了。

齐山琥珀的例子

我使用密码和 iv 与示例相同。

            Crypt cryptObj = new Crypt();

            string encryStr = cryptObj.Encrypt(original, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);
            string decryStr = cryptObj.Decrypt(encryStr, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);

本例与Dan Esparza一样,文件比较失败

我认为问题应该出在我的文件importing/exporting,可能是文件中的特殊字符、EOL 或BOM。我在写文件的时候也尝试了不同的编码,但是没有发现。

有没有人有什么想法?

我不知道为什么在 encryption/decryption 过程中需要密码,为什么在基本上使用字节(文件)时需要 encrypt/decrypt 字符串。

这里是一个使用字节和key/iv(伪)随机生成的例子:

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

namespace AesDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] key = null;
            byte[] iv = null;
            byte[] bytesToEncrypt = null;
            byte[] encryptedBytes = null;
            byte[] decryptedBytes = null;

            // generate key and iv to use for encryption/decryption. 
            using (RijndaelManaged aesAlg = new RijndaelManaged())
            {
                aesAlg.GenerateKey();
                aesAlg.GenerateIV();
                key = aesAlg.Key;
                iv = aesAlg.IV;
            }

            // original bytes
            bytesToEncrypt = File.ReadAllBytes(@"c:\exe");
            Console.WriteLine("Bytes read: {0}",bytesToEncrypt.Length);

            // encrypt
            encryptedBytes = CryptoAes.Encrypt(bytesToEncrypt, key, iv);
            Console.WriteLine("Encrypted bytes length: {0}", encryptedBytes.Length);

            // decrypt
            decryptedBytes = CryptoAes.Decrypt(encryptedBytes, key, iv);
            Console.WriteLine("Decrypted bytes length: {0}", decryptedBytes.Length);

            // compare
            Console.WriteLine("Decrypted bytes same as original bytes: {0}", Convert.ToBase64String(decryptedBytes) == Convert.ToBase64String(bytesToEncrypt));
            Console.ReadLine();
        }
    }

    internal sealed class CryptoAes
    {
        /// <summary>
        /// Encrypts data with symetric key
        /// </summary>
        /// <param name="data">Data to be encrypted</param>
        /// <param name="key">Symetric key</param>
        /// <param name="iv">Initialization vector</param>
        /// <returns>Encrypted data</returns>
        public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
        {
            byte[] encryptedData = null;

            if (data == null)
                throw new ArgumentNullException("data");

            if (data == key)
                throw new ArgumentNullException("key");

            if (data == iv)
                throw new ArgumentNullException("iv");

            using (RijndaelManaged aesAlg = new RijndaelManaged())
            {
                aesAlg.Key = key;
                aesAlg.IV = iv;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
                encryptedData = encryptor.TransformFinalBlock(data, 0, data.Length);
            }

            return encryptedData;
        }

        /// <summary>
        /// Decrypts data with symetric key
        /// </summary>
        /// <param name="data">Encrypted data</param>
        /// <param name="key">Symetric key</param>
        /// <param name="iv">Initialization vector</param>
        /// <returns>Decrypted data</returns>
        public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
        {
            byte[] decryptedData = null;

            if (data == null)
                throw new ArgumentNullException("data");

            if (data == key)
                throw new ArgumentNullException("key");

            if (data == iv)
                throw new ArgumentNullException("iv");

            using (RijndaelManaged aesAlg = new RijndaelManaged())
            {
                aesAlg.Key = key;
                aesAlg.IV = iv;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                decryptedData = decryptor.TransformFinalBlock(data, 0, data.Length);
            }

            return decryptedData;
        }
    }
}

ASE文件加密

internal const string Inputkey = "560A18CD-6346-4CF0-A2E8-671F9B6B9EA9";
    ///<summary>
    /// Arvind - 23/11/2017.
    ///
    /// Encrypts a file using Rijndael algorithm.
    ///</summary>
    ///<param name="inputFile"></param>
    ///<param name="outputFile"></param>
    public static void EncryptFile(string inputFile, string outputFile)
    {
        try
        {
            string password = @"+kdkdkdjd8656589$**hh$^JHJBKLJJH#$$$__+0-f5546%$$^5434+"; // Secret Key
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = UE.GetBytes(password);

            string cryptFile = outputFile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
            Rijndael RMCrypto = NewRijndaelManaged(password);

            var encryptor = RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV);

            CryptoStream cs = new CryptoStream(fsCrypt,
                encryptor,
                CryptoStreamMode.Write);

            FileStream fsIn = new FileStream(inputFile, FileMode.Open);

            int data;
            while ((data = fsIn.ReadByte()) != -1)
                cs.WriteByte((byte)data);


            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
        }
        catch (Exception ex)
        {
            throw new ApplicationException("Encryption failed!" + ex.Message);
        }
    }


    /// <summary>
    /// Create a new RijndaelManaged class and initialize it
    /// </summary>
    /// <param name="salt" />The pasword salt
    /// <returns></returns>
    private static RijndaelManaged NewRijndaelManaged(string salt)
    {
        if (salt == null) throw new ArgumentNullException("salt");
        var saltBytes = Encoding.ASCII.GetBytes(salt);
        var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);

        var aesAlg = new RijndaelManaged();
        aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
        aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

        return aesAlg;
    }

    **File decryption**
///<summary>
    /// Arvind - 23/11/2017.
    ///
    /// Decrypts a file using Rijndael algorithm.
    ///</summary>
    ///<param name="inputFile"></param>
    ///<param name="outputFile"></param>
    public static void DecryptDatabaseFile(string inputFile, string outputFile)
    {
        try
        {
            string password = System.Configuration.ConfigurationManager.AppSettings["encryptionKey"];
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = UE.GetBytes(password);

            FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
            var aesAlg = NewRijndaelManaged(password);
            var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            CryptoStream cs = new CryptoStream(fsCrypt,
               decryptor,
                CryptoStreamMode.Read);

            FileStream fsOut = new FileStream(outputFile, FileMode.Create);
            int data;
            while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);

            fsOut.Close();
            cs.Close();
            fsCrypt.Close();

        }
        catch (Exception ex)
        {
            throw new ApplicationException("decryption Fail!!" + ex.Message);
        }
    }