【问题标题】:AesManaged - Padding is Invalid and Cannot Be Removed - Reading from .Txt FileAesManaged - 填充无效且无法删除 - 从 .Txt 文件中读取
【发布时间】:2019-05-21 20:49:40
【问题描述】:

我正在尝试将加密数据保存到文本文件中,然后打开并解密它。当我尝试解密它时,我收到错误“填充无效且无法删除”。我直接使用 Microsoft 的示例代码进行加密和解密。

这是我加密和保存文件的代码:

                    string json = JsonConvert.SerializeObject(credentials);
                    using (AesManaged myAes = new AesManaged())
                    {

                        byte[] encrypted = ControlHelperscs.EncryptStringToBytes_Aes(json, myAes.Key, myAes.IV);
                        File.WriteAllBytes(subPath, encrypted);
                    }

这是我检索和解密文件的代码:

                using (AesManaged myAes = new AesManaged())
            {

                    byte[] file = File.ReadAllBytes(subPath);

                    string decrypt = ControlHelperscs.DecryptStringFromBytes_Aes(file, myAes.Key, myAes.IV);
                    credentials = JsonConvert.DeserializeObject<LoginModel>(decrypt);

            }

这里是加密和解密方法:

        public 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 AesManaged object
        // with the specified key and IV.
        using (AesManaged aesAlg = new AesManaged())
        {
            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;

    }

    public 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 AesManaged object
        // with the specified key and IV.
        using (AesManaged aesAlg = new AesManaged())
        {
            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;

    }

【问题讨论】:

  • 看起来您使用的是固定 IV - 这在很大程度上违背了 CBC 模式的意义。这是不安全的。
  • 实际上,我从 Microsoft docs.microsoft.com/en-us/dotnet/api/… 获得了该代码。这就是为什么我不明白为什么它不能正常工作。
  • @Jesse C. Slicer(收到错误:“FlushFinalBlock() 方法在 CryptoStream 上被调用了两次。它只能被调用一次。”

标签: encryption


【解决方案1】:

很抱歉,我删除了我的评论(在这种情况下是错误的),但我修改了您的示例以减少样板文件并能够正确加密和解​​密。问题是您正在生成一个新的和不同的密钥/IV 对来从您用来加密的密钥/IV 对中解密。当然不能解密。所以,这是使它工作的部分:

        byte[] key;
        byte[] iv;

        string json = JsonConvert.SerializeObject(credentials);
        using (AesManaged myAes = new AesManaged())
        {
            key = myAes.Key;
            iv = myAes.IV;
            byte[] encrypted = ControlHelperscs.EncryptStringToBytes_Aes(json, key, iv);
            File.WriteAllBytes(subPath, encrypted);
        }

        byte[] file = File.ReadAllBytes(subPath);

        string decrypt = ControlHelperscs.DecryptStringFromBytes_Aes(file, key, iv);
        credentials = JsonConvert.DeserializeObject<LoginModel>(decrypt);

这里是稍微改进的重载方法,使其更紧凑:

    public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
    {
        // Check arguments.
        if (plainText is null)
        {
            throw new ArgumentNullException(nameof(plainText));
        }

        if (plainText.Length == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(plainText), plainText, "length cannot be zero");
        }

        if (key is null)
        {
            throw new ArgumentNullException(nameof(key));
        }

        if (key.Length == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(key), key, "length cannot be zero");
        }

        if (iv is null)
        {
            throw new ArgumentNullException(nameof(iv));
        }

        if (iv.Length == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(iv), iv, "length cannot be zero");
        }

        // Create an AesManaged object
        // with the specified key and IV.
        // Create an encryptor to perform the stream transform.
        // Create the streams used for encryption.
        using (SymmetricAlgorithm aesAlg = new AesManaged { Key = key, IV = iv })
        using (ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
        using (MemoryStream msEncrypt = new MemoryStream())
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        using (TextWriter swEncrypt = new StreamWriter(csEncrypt))
        {
            // Write all data to the stream.
            swEncrypt.Write(plainText);
            swEncrypt.Flush();
            csEncrypt.FlushFinalBlock();

            // Return the encrypted bytes from the memory stream.
            return msEncrypt.ToArray();
        }
    }

    public static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
    {
        // Check arguments.
        if (cipherText is null)
        {
            throw new ArgumentNullException(nameof(cipherText));
        }

        if (cipherText.Length ==  0)
        {
            throw new ArgumentOutOfRangeException(nameof(cipherText), cipherText, "length cannot be zero");
        }

        if (key is null)
        {
            throw new ArgumentNullException(nameof(key));
        }

        if (key.Length == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(key), key, "length cannot be zero");
        }

        if (iv is null)
        {
            throw new ArgumentNullException(nameof(iv));
        }

        if (iv.Length == 0)
        {
            throw new ArgumentOutOfRangeException(nameof(iv), iv, "length cannot be zero");
        }

        // Create an AesManaged object
        // with the specified key and IV.
        // Create a decryptor to perform the stream transform.
        // Create the streams used for decryption.
        using (SymmetricAlgorithm aesAlg = new AesManaged { Key = key, IV = iv })
        using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
        using (Stream msDecrypt = new MemoryStream(cipherText))
        using (Stream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        using (TextReader srDecrypt = new StreamReader(csDecrypt))
        {
            // Read the decrypted bytes from the decrypting stream
            // and place them in a string.
            return srDecrypt.ReadToEnd();
        }
    }

【讨论】:

  • 感谢您的帮助,这里的问题是用户永远不会以保存的相同方法打开保存的文本文件,因此无法使用相同的键。我需要一种方法来知道解密时密钥是什么。所以他们的密钥必须保存到文件系统中。我将尝试将密钥保存到文本文件并打开,看看是否可行。
  • 非常感谢!非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
相关资源
最近更新 更多