Aes decryptor gives an empty string

I have a problem with AES encryption / decryption. The commented code worked, but sometimes it gave the error "the filling is invalid and cannot be deleted", so I changed it, as explained here. The filling is invalid and cannot be deleted. Exception when decrypting a string using "AesManaged" C #

but when I tried this, the code below when decrypting gives an empty string. I do not know where I am wrong. The two static functions bytesToString and stringToBytes have nothing to do with encryption, and I use them elsewhere. The key length and block size are OKAY. I found this in debbuger:

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

I am working on 3.5.NET Visual STudio 2008

there is prtscr from the debugger, as you can see, after you left the block, encrypted with a length of 0 bytes, and the cryptostrel has some exceptions

Print screen from debugger

How to fix it? Please give me some tips.

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

Well, maybe I will explain the whole situation a little more. I wrote my own secure email. I have 2x encryption. Communication between the server and the client is encrypted by RSA and AES. Messages created by users are also encrypted with RSA + AES.

Post Message

as follows:

  • The client connects to the server.
  • They establish a secure connection (the server sends its public key, the client generates an AES key, encrypts it through the server’s public key and sends it to the server. After that, the server and the client use the AES key for communication).
  • The client creates the message in XML, the message may contain files that are read on base64, and after that they are encrypted using AES.
  • The message is written to db.

Receiving a message is as follows:

  • Connection to the server.
  • Establish a secure connection.
  • Receive messages from the server.
  • Decrypt the AES key using the RSA private key.
  • Decrypt the message using the decrypted AES key.
  • If there are files, decrypt them with AES and base64_decode in bytes and save.

Now the problem is encryption of big data. Sometimes there are even 200-300 kB.

Another interesting thing that I discovered is that when I run the code through the debugger, it works, but when I run the code without it. This does not work.


Decision

I found a solution to the problem. Since I used AES encryption / decryption twice very fast one after another with different / ivs keys, the garbage collector did not clear these objects. The solution was added

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

before returning DecryptStringFromBytes_Aes and EncryptStringToBytes_Aes

I hope this helps someone who has the same problem as mine.

0
c # cryptography aes rijndaelmanaged
source share
1 answer

The way you used streams meant that there were no data in the underlying streams, I don't know why, but I found an alternative approach that I reworked.

Using the following code, you can launch the console application and then modify it to work for your purposes. Let me know how it works out:

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

Sources for providing this answer: Using AES encryption in .NET - CryptographicException saying indentation is invalid and cannot be removed

0
source share

All Articles