AES解密文件损坏后,C#

时间:2018-08-29 15:37:28

标签: c# encryption aes

使用AES算法解密文件后,我收到此消息:

Image of message - The file cannot be opened because there are problems with the contents

但是,当我单击“确定”时,文件将正确打开,而不会丢失任何数据。

它使用户认为文件有问题。

我的加密和解密代码:

    /// <summary>
    /// AES strong encryption logic used
    /// </summary>
    /// <param name="encfilepath">file path which need to encrypt</param>
    /// <param name="enckey">key used to decrypt</param>
    public static void AESEncryptFile(string encfilepath, byte[] enckey)
    {
        byte[] bytesToBeEncrypted = System.IO.File.ReadAllBytes(System.Security.SecurityElement.Escape(encfilepath));

        // Hash the password with SHA256
        byte[] passwordBytes = SHA256.Create().ComputeHash(enckey);

        //create the new folder to for decryption
        var decryptedFilePath = Path.GetDirectoryName(encfilepath) + @"\" + Guid.NewGuid() + @"\" + Path.GetFileName(encfilepath);
        if (!Directory.Exists(Path.GetDirectoryName(decryptedFilePath)))
            Directory.CreateDirectory(Path.GetDirectoryName(decryptedFilePath));

        //decrypt the plain file and store in decryption folder
        AES_Encrypt(encfilepath, decryptedFilePath, passwordBytes);

        //move the file from decryption folder to actual folder
        if (File.Exists(encfilepath))
            File.Delete(encfilepath);
        File.Move(decryptedFilePath, encfilepath);
        Directory.Delete(Path.GetDirectoryName(decryptedFilePath));
    }

    /// <summary>
    /// AES strong encryption logic used
    /// </summary>
    /// <param name="inputFile">this is plain file path which want to encrypt</param>
    /// <param name="outputFile">this is output file where encrypt file need to save</param>
    /// <param name="passwordBytes">password byte</param>
    private static void AES_Encrypt(string inputFile, string outputFile, byte[] passwordBytes)
    {
        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        string cryptFile = outputFile;
        FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

        RijndaelManaged AES = new RijndaelManaged();

        AES.KeySize = 256;
        AES.BlockSize = 128;


        var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Padding = PaddingMode.Zeros;

        AES.Mode = CipherMode.CBC;

        CryptoStream cs = new CryptoStream(fsCrypt,
             AES.CreateEncryptor(),
            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();

    }


    /// <summary>
    /// AES strong encryption logic used
    /// </summary>
    /// <param name="encfilepath">file path which need to encrypt</param>
    /// <param name="enckey">key used to decrypt</param>

    /// <summary>
    /// Decrypt the encrypted file file using AES algorithm
    /// </summary>
    /// <param name="encryptedFilePath">Selected encrypted file</param>
    /// <param name="decryptFilePath">Decrypt file path</param>
    /// <param name="userFileName">Selected encrypted file user file name</param>
    /// <returns>Value of bool - File decrypted status</returns>
    //public bool DecryptFile(string encryptedFilePath, string decryptFilePath, string userFileName)
    public static bool AESDecryptFile(string encryptedFilePath, out string decryptFilePath, byte[] encryptionKey)
    {
        var isDecrypted = false;
        try
        {
            decryptFilePath = Path.GetDirectoryName(encryptedFilePath) + @"\" + Guid.NewGuid() + @"\" + Path.GetFileName(encryptedFilePath);
            if (!Directory.Exists(Path.GetDirectoryName(decryptFilePath)))
                Directory.CreateDirectory(Path.GetDirectoryName(decryptFilePath));
            var passwordBytes = SHA256.Create().ComputeHash(encryptionKey);
            AES_Decrypt(encryptedFilePath, decryptFilePath, passwordBytes);
            isDecrypted = true;
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return isDecrypted;
    }

    /// <summary>
    /// AES strong encryption logic used
    /// </summary>
    /// <param name="inputFile">this is cypertext file path which want to decrypt</param>
    /// <param name="outputFile">this is output file where decrypted file need to save</param>
    /// <param name="passwordBytes">password byte</param>
    public static void AES_Decrypt(string inputFile, string outputFile, byte[] passwordBytes)
    {

        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);

        RijndaelManaged AES = new RijndaelManaged();

        AES.KeySize = 256;
        AES.BlockSize = 128;


        var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Padding = PaddingMode.Zeros;

        AES.Mode = CipherMode.CBC;

        CryptoStream cs = new CryptoStream(fsCrypt,
            AES.CreateDecryptor(),
            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();

    }

我重用了以下代码: (AES encryption on large files

2 个答案:

答案 0 :(得分:1)

编辑:此功能不适用于500MB或更大的文件。

我上周在C#中使用了AES加密。我用了这个例子:

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=netframework-4.7.2

这是我的代码:

使用加密方法:

string password = "password";
using (Aes aes = Aes.Create())
        {
           //Encrypt the string
           byte[] encrypted = EncryptStringToBytes_Aes(password, aes.Key, aes.IV);
           //Decrypt the string
           string roundtrip = DecryptStringFromBytes_Aes(encrypted, aes.Key, aes.IV);
           //Convert the key, iv and encrypted message to base 64 string to get them in text
           Convert.ToBase64String(encrypted)
        }

两种加密/解密方法:

static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
    {
        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");
        byte[] encrypted;

        // Create an Aes object
        // with the specified key and IV.
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            // Create an encryptor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }


        // Return the encrypted bytes from the memory stream.
        return encrypted;

    }

    static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
    {
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");

        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;

        // Create an Aes object
        // with the specified key and IV.
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            // Create a decryptor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {

                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }

        }

        return plaintext;

    }

答案 1 :(得分:0)

我同意对我的帖子的评论。

最后,我使用了以下加密逻辑。而且对我来说很好。

AES encryption on large files

如果对此逻辑有任何疑问,请发表评论。