AES解密给空字符串 [英] Aes decryptor gives empty string

查看:1479
本文介绍了AES解密给空字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题,AES加密/解密。该评论code的工作,但有时也给了错误填充是无效的不能删除,所以我改变了它,因为它是这里<一个解释href="http://stackoverflow.com/questions/10469819/padding-is-invalid-and-cannot-be-removed-exception-while-decrypting-string-using">Padding是无效的,不能删除异常,而使用&QUOT解密串; AesManaged&QUOT; C#

I have problem with AES encryption/decryption. The commented code worked but sometimes gave error "padding is invalid and cannot be removed" so I changed it as it is explained here Padding is invalid and cannot be removed Exception while decrypting string using "AesManaged" C#

但是当我解密过程中尝试了在code下面给出了一个空字符串。我不知道我在哪里出错。这两个静态函数bytesToString和stringToBytes无关加密和我使用它们在其他一些地方。密钥长度和块大小是好的。 我发现这debbuger:

but when I tried it the code below during decryption gives an empty string. I don't know where I make mistake. The two static functions bytesToString and stringToBytes has nothing to do with encryption and I use them in some other place. The key length and block size is OKAY. I found this in debbuger:

csEncrypt.Length'引发了异常类型的System.NotSupportedException'

"'csEncrypt.Length' threw an exception of type 'System.NotSupportedException'"

我工作在.NET 3.5的Visual Studio 2008

I Work on 3.5 .NET Visual STudio 2008

下面是调试器作为美国可以离开块加密后看到prtscr为0字节长的CryptoStream有一些例外

here is prtscr from debugger as u can see after leaving block encrypted is 0 byte long and cryptostream has some exceptions

从调试器打印屏幕

如何解决?请给我一些线索。

How to fix it? Please give me some clues.

static class Aes
{
    public static string bytesToHexString(byte[] key)
    {
        return BitConverter.ToString(key).Replace("-", String.Empty);
    }

    public static byte[] stringToBytes(string key)
    {
        return Enumerable.Range(0, key.Length)
                 .Where(x => x % 2 == 0)
                 .Select(x => Convert.ToByte(key.Substring(x, 2), 16))
                 .ToArray();
    }

    public static void generateKeyAndIv(out byte[] key, out byte[] IV)
    {
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            aesAlg.Padding = PaddingMode.None;
            //aesAlg.Mode = CipherMode.CBC;
            aesAlg.GenerateKey();
            aesAlg.GenerateIV();
            key = aesAlg.Key;
            IV = aesAlg.IV;
        }
    }
    public static string EncryptStringToString(string plainText, byte[] Key, byte[] IV)
    {
        byte[] bytes =EncryptStringToBytes_Aes(plainText, Key, IV);
        return Convert.ToBase64String(bytes);
        //return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
    }

    public static string DecryptStringToString(string cipherText, byte[] Key, byte[] IV)
    {
        //byte[] bytes = Encoding.UTF8.GetBytes(cipherText);
        byte[] bytes = Convert.FromBase64String(cipherText);
        return DecryptStringFromBytes_Aes(bytes, Key, IV);
    }

    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("Key");
        /*byte[] encrypted;
        // Create an AesCryptoServiceProvider object 
        // with the specified key and IV. 
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.Key = Key;
            aesAlg.IV = IV;
            // Create a decrytor 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();
            }
        }*/
        byte[] encrypted;
        // Create an AesManaged object
        // with the specified key and IV.
        using (AesManaged aesAlg = new AesManaged())
        {

            // Create a decrytor to perform the stream transform.
            aesAlg.Padding = PaddingMode.None;
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

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

        //return encrypted;


        // 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 AesCryptoServiceProvider object 
        // with the specified key and IV. 
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Mode = CipherMode.CBC;
            aesAlg.Key = Key;
            aesAlg.IV = IV;
            // Create a decrytor 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;

    }
}

好吧,也许我会解释整个情况多一点。我写我自己安全的电子邮件。我有2个加密。服务器和客户端之间的通信是通过RSA和AES加密。同时用户创建的消息由RSA + AES加密。

OK, maybe I will explain the whole situation a bit more. I wrote my own secure e-mail. I have 2x encryption. The communication between server and client is encrypted by RSA and AES. Also messages created by users are encrypted by RSA + AES.

发送的消息是这样的:

  1. 客户端连接到服务器。
  2. 在他们建立安全连接(服务器发送其公钥,客户端生成通过服务器的公共密钥的AES密钥进行加密,并将其发送给服务器。该服务器和客户端后使用AES密钥进行通信)。
  3. 在客户端创建XML消息,消息可以包含读为base64这之后,他们用AES进行加密的文件。
  4. 在该消息被写入到数据库。

recieving消息是这样的:

recieving message look like:

  1. 连接到服务器。
  2. 在建立安全连接。
  3. 从服务器获取信息。
  4. 在使用RSA私钥解密AES密钥。
  5. 在使用解密的AES密钥解密消息。
  6. 如果有文件,然后使用AES和base64_de code它们解密他们字节和保存。

现在的问题是,随着大数据加密。即使200-300 KB有时问题。

Now the problem is with encryption of large data. Even 200-300 kB is sometimes problem.

另一个有趣的事情,我发现的是,当我通过调试运行code它的工作原理,但是当我运行code离不开它。这是行不通的。

Another interesting thing I've discovered is that when I run the code via debugger it works but when I run code without it. It doesn't work.

解决方案

我找到了问题的解决方案。因为我以后彼此不同的密钥/ IVS垃圾收集器使用AES加密/解密两次非常快没清理这些对象。该溶液中加入

I found the solution of problem. Because I used AES encryption/decryption twice very fast after each other with different keys/ivs Garbage Collector didn't clean these objects. The solution was adding

GC.Collect();
GC.WaitForPendingFinalizers();

刚刚返回值由DecryptStringFromBytes_Aes和EncryptStringToBytes_Aes之前

just before returning value by DecryptStringFromBytes_Aes and EncryptStringToBytes_Aes

我希望这会帮助别人谁是有同样的问题,像我了。

I hope that it will help someone who is having same issue like I had.

推荐答案

您正在使用的流意味着没有数据被写入到底层数据流的方式,我不知道为什么,但我没有找到一个替代的办法,我已经返工。

The way you were using the streams meant that there was no data being written to the underlying streams, I do not know why but I did find an alternative approach that I have reworked.

通过以​​下code,你应该能够作为一个控制台应用程序运行,然后重新塑造它,所以它适用于您的目的。让我知道如何去:

With the following code you should be able to run as a console application and then reshape it so it works for your purposes. Let me know how it goes:

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

namespace Encrypto
{
    public static class Program
    {
        public static void Main()
        {

            const string password = "test";
            const string text = "test";
            var cipherText = Aes.Encrypt(password, text);
            var decrypted = Aes.Decrypt(password, cipherText);

            Console.WriteLine(decrypted);
            Console.ReadKey();
        }
    }

    internal static class Aes
    {
        public static EncryptedData Encrypt(string password, string data)
        {
            return Transform(true, password, data, null) as EncryptedData;
        }

        public static string Decrypt(string password, EncryptedData data)
        {
            return Transform(false, password, data.DataString, data.SaltString) as string;
        }

        private static object Transform(bool encrypt, string password, string data, string saltString)
        {
            using (var aes = new AesManaged())
            {
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                var keyLen = aes.KeySize/8;
                var ivLen = aes.BlockSize/8;
                const int saltSize = 8;
                const int iterations = 8192;

                var salt = encrypt ? new byte[saltSize] : Convert.FromBase64String(saltString);
                if (encrypt)
                {
                    new RNGCryptoServiceProvider().GetBytes(salt);
                }

                var bcKey = new Rfc2898DeriveBytes("BLK" + password, salt, iterations).GetBytes(keyLen);
                var iv = new Rfc2898DeriveBytes("IV" + password, salt, iterations).GetBytes(ivLen);
                var macKey = new Rfc2898DeriveBytes("MAC" + password, salt, iterations).GetBytes(16);

                aes.Key = bcKey;
                aes.IV = iv;

                var rawData = encrypt ? Encoding.UTF8.GetBytes(data) : Convert.FromBase64String(data);

                using (var transform = encrypt ? aes.CreateEncryptor() : aes.CreateDecryptor())
                using (var memoryStream = encrypt ? new MemoryStream() : new MemoryStream(rawData))
                using (var cryptoStream = new CryptoStream(memoryStream, transform, encrypt ? CryptoStreamMode.Write : CryptoStreamMode.Read))
                {
                    if (encrypt)
                    {
                        cryptoStream.Write(rawData, 0, rawData.Length);
                        cryptoStream.FlushFinalBlock();
                        return new EncryptedData(salt, macKey, memoryStream.ToArray());
                    }
                    var originalData = new byte[rawData.Length];
                    var count = cryptoStream.Read(originalData, 0, originalData.Length);

                    return Encoding.UTF8.GetString(originalData, 0, count);
                }
            }
        }

        public class EncryptedData
        {
            public EncryptedData(byte[] salt, byte[] mac, byte[] data)
            {
                Salt = salt;
                MAC = mac;
                Data = data;
            }

            private byte[] Salt { get; set; }

            public string SaltString
            {
                get { return Convert.ToBase64String(Salt); }
            }

            private byte[] MAC { get; set; }

            private byte[] Data { get; set; }

            public string DataString
            {
                get { return Convert.ToBase64String(Data); }
            }
        }
    }
}

,用于提供这样的回答:<一href="http://stackoverflow.com/questions/4545387/using-aes-encryption-in-net-cryptographicexception-saying-the-padding-is-inva">Using AES加密在.NET - CryptographicException称填充是无效的不能删除

这篇关于AES解密给空字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆