title: Using AES encryption in .NET - CryptographicException saying the padding is invalid and cannot be removed
body: <p>I wrote some AES encryption code in C# and I am having trouble getting it to encrypt and decrypt properly. If I enter "test" as the passphrase and "This data must be kept secret from everyone!" I receive the following exception:</p>
  
  <pre><code>System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
     at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]&amp; outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
     at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
     at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
     at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
     at System.IO.Stream.Close()
     at System.IO.Stream.Dispose()
     ...
  </code></pre>
  
  <p>And if I enter something less than 16 characters I get no output.</p>
  
  <p>I believe I need some special handling in the encryption since AES is a block cipher, but I'm not sure exactly what that is, and I wasn't able to find any examples on the web showing how. Here is my code:</p>
  
  <pre><code>using System;
  using System.IO;
  using System.Security.Cryptography;
  using System.Text;
  
  public static class DatabaseCrypto
  {
      public static EncryptedData Encrypt(string password, string data)
      {
          return DatabaseCrypto.Transform(true, password, data, null, null) as EncryptedData;
      }
  
      public static string Decrypt(string password, EncryptedData data)
      {
          return DatabaseCrypto.Transform(false, password, data.DataString, data.SaltString, data.MACString) as string;
      }
  
      private static object Transform(bool encrypt, string password, string data, string saltString, string macString)
      {
          using (AesManaged aes = new AesManaged())
          {
              aes.Mode = CipherMode.CBC;
              aes.Padding = PaddingMode.PKCS7;
              int key_len = aes.KeySize / 8;
              int iv_len = aes.BlockSize / 8;
              const int salt_size = 8;
              const int iterations = 8192;
  
              byte[] salt = encrypt ? new byte[salt_size] : Convert.FromBase64String(saltString);
              if (encrypt)
              {
                  new RNGCryptoServiceProvider().GetBytes(salt);
              }
  
              byte[] bc_key = new Rfc2898DeriveBytes("BLK" + password, salt, iterations).GetBytes(key_len);
              byte[] iv = new Rfc2898DeriveBytes("IV" + password, salt, iterations).GetBytes(iv_len);
              byte[] mac_key = new Rfc2898DeriveBytes("MAC" + password, salt, iterations).GetBytes(16);
  
              aes.Key = bc_key;
              aes.IV = iv;
  
              byte[] rawData = encrypt ? Encoding.UTF8.GetBytes(data) : Convert.FromBase64String(data);
  
              using (ICryptoTransform transform = encrypt ? aes.CreateEncryptor() : aes.CreateDecryptor())
              using (MemoryStream memoryStream = encrypt ? new MemoryStream() : new MemoryStream(rawData))
              using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, encrypt ? CryptoStreamMode.Write : CryptoStreamMode.Read))
              {
                  if (encrypt)
                  {
                      cryptoStream.Write(rawData, 0, rawData.Length);
  
                      return new EncryptedData(salt, mac_key, memoryStream.ToArray());
                  }
                  else
                  {
                      byte[] originalData = new byte[rawData.Length];
                      int count = cryptoStream.Read(originalData, 0, originalData.Length);
  
                      return Encoding.UTF8.GetString(originalData, 0, count);
                  }
              }
          }
      }
  }
  
  public class EncryptedData
  {
      public EncryptedData()
      {
      }
  
      public EncryptedData(byte[] salt, byte[] mac, byte[] data)
      {
          this.Salt = salt;
          this.MAC = mac;
          this.Data = data;
      }
  
      public EncryptedData(string salt, string mac, string data)
      {
          this.SaltString = salt;
          this.MACString = mac;
          this.DataString = data;
      }
  
      public byte[] Salt
      {
          get;
          set;
      }
  
      public string SaltString
      {
          get { return Convert.ToBase64String(this.Salt); }
          set { this.Salt = Convert.FromBase64String(value); }
      }
  
      public byte[] MAC
      {
          get;
          set;
      }
  
      public string MACString
      {
          get { return Convert.ToBase64String(this.MAC); }
          set { this.MAC = Convert.FromBase64String(value); }
      }
  
      public byte[] Data
      {
          get;
          set;
      }
  
      public string DataString
      {
          get { return Convert.ToBase64String(this.Data); }
          set { this.Data = Convert.FromBase64String(value); }
      }
  }
  
      static void ReadTest()
      {
          Console.WriteLine("Enter password: ");
          string password = Console.ReadLine();
  
          using (StreamReader reader = new StreamReader("aes.cs.txt"))
          {
              EncryptedData enc = new EncryptedData();
              enc.SaltString = reader.ReadLine();
              enc.MACString = reader.ReadLine();
              enc.DataString = reader.ReadLine();
  
              Console.WriteLine("The decrypted data was: " + DatabaseCrypto.Decrypt(password, enc));
          }
      }
  
      static void WriteTest()
      {
          Console.WriteLine("Enter data: ");
          string data = Console.ReadLine();
          Console.WriteLine("Enter password: ");
          string password = Console.ReadLine();
  
          EncryptedData enc = DatabaseCrypto.Encrypt(password, data);
  
          using (StreamWriter stream = new StreamWriter("aes.cs.txt"))
          {
              stream.WriteLine(enc.SaltString);
              stream.WriteLine(enc.MACString);
              stream.WriteLine(enc.DataString);
  
              Console.WriteLine("The encrypted data was: " + enc.DataString);
          }
      }
  </code></pre>