Aes解密器给出空字符串

我有AES加密/解密的问题。 注释的代码工作,但有时给出错误“填充无效,无法删除”所以我更改它,因为它在这里解释填充无效,无法删除exception,而使用“AesManaged”解密字符串C#

但是当我尝试它时,解密过程中的代码会给出一个空字符串。 我不知道哪里弄错了。 两个静态函数bytesToString和stringToBytes与加密无关,我在其他地方使用它们。 密钥长度和块大小是OKAY。 我在debbuger中找到了这个:

“’csEncrypt.Length’引发了’System.NotSupportedException’类型的exception”

我在3.5 .NET Visual STudio 2008上工作

这是来自调试器的prtscr,因为你可以看到离开块后加密的是0字节长,而cryptostream有一些例外

从调试器打印屏幕

怎么解决? 请给我一些线索。

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加密。

发送消息看起来像:

  1. 客户端连接到服务器。
  2. 它们建立安全连接(服务器发送其公钥,客户端生成AES密钥通过服务器的公钥加密它并将其发送到服务器。之后服务器和客户端使用AES密钥进行通信)。
  3. 客户端以XML格式创建消息,消息可以包含读取到base64的文件,然后使用AES加密。
  4. 消息将写入db。

接收消息看起来像:

  1. 连接到服务器。
  2. 建立安全连接。
  3. 从服务器获取消息。
  4. 使用RSA私钥解密AES密钥。
  5. 使用解密的AES密钥解密消息。
  6. 如果有文件,则使用AES解密它们,并将base64_decode解码为字节并保存。

现在的问题是加密大数据。 甚至200-300 kB有时也是问题。

我发现的另一个有趣的事情是,当我通过调试器运行代码时它可以工作,但是当我运行没有它的代码时。 它不起作用。


我找到了问题的解决方案。 因为我使用不同的密钥/ ivs彼此非常快地使用AES加密/解密两次垃圾收集器没有清理这些对象。 解决方案是添加

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

就在DecryptStringFromBytes_Aes和EncryptStringToBytes_Aes返回值之前

我希望它会帮助那些遇到同样问题的人。

您使用流的方式意味着没有数据写入底层流,我不知道为什么,但我确实找到了我已经重做的替代方法。

使用以下代码,您应该能够作为控制台应用程序运行,然后重新整形,以便它适用于您的目的。 让我知道事情的后续:

 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); } } } } } 

提供此答案的来源: 在.NET中使用AES加密 – CryptographicException表示填充无效且无法删除