C# AES解密文件损坏后C

C# AES解密文件损坏后C,c#,encryption,aes,C#,Encryption,Aes,使用AES算法解密文件后,我收到以下消息: 但是,当我单击“确定”时,文件将正常打开,并且不会丢失任何数据 它会让用户认为文件有问题 我的加密和解密代码: /// <summary> /// AES strong encryption logic used /// </summary> /// <param name="encfilepath">file path which need to encrypt</param&

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

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

它会让用户认为文件有问题

我的加密和解密代码:

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

    }
我重用了以下代码:

编辑:这不适用于500MB或更大的文件

我上周在C中使用了AES加密。我使用了以下示例:

这是我的密码:

使用该方法加密:

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;

    }

我同意我的评论

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


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

比较原始文件和解密文件。我怀疑BOM编码并不完美,在文件的开头会有两个外来字符。不过这只是一个理论:这不是很好的代码,它一次工作一个字节,不处理任何东西,使用非随机salt&使用部分键作为IV是个坏主意,原因有几个,尤其是因为它使输出具有确定性。我建议在继续之前找一个更好的例子。@Kevin-不,如果你使用的东西是合理的,解密代码应该自动删除填充。填充机制的设计是为了能够识别、验证和剥离最后一个块中的填充。@Kevin-是的,.NET加密类绝对可以为您完成这项工作。你从哪里来的这种奇怪的信念?加密过程中添加填充但解密过程中未能去除填充的加密库被设计破坏。这是因为a库有缺陷,还是因为b未能检查返回值,这些返回值告诉您缓冲区中有多少包含有效数据?多年来,我也以各种形式使用了加密库,但我从未遇到过您描述的情况。这些代码需要一些调整才能在生产中正常工作,这取决于您与谁交谈。但从RijndaelManaged搬到AesManaged可能是个好主意。我同意你应该把你自己版本的代码放在这里,因为只有链接,外部答案也不在范围之内。@LapX:你发送的链接对大文件不起作用,它会给你执行的记忆。但在我的场景中,我需要使用500MB以上的文件进行加密。我使用它来加密密码,而不是整个文件。我仍然会发布我的代码版本。我不知道尺寸限制。