title: AES encryption in C Sharp and decryption in Android using PBKDF2WithHmacSHA1
body: <p>I am using Android and I am trying to decrypt a message encrypted in a C Sharp Server.</p>
  
  <p>Below is the code for the C# Cryptor, that uses 256 bit long Keys, 128 bit long IV, 5000 Iterations. It uses <strong>Rfc2898DeriveBytes Class</strong>, so that is the same as <strong>PBKDF2WithHmacSHA1</strong> in Android.</p>
  
  <p>The decrypt function of the C# Cryptor takes as its IV the (reversed) first 128 bits of the 256 bit long key.</p>
  
  <pre><code>namespace CompanyName.Framework.Encryption
  {
      internal class SymmetricCryptor : ISymmetricCryptor
      {
          internal static int KeyLengthInBytes = 32; 
  
          internal int Iterations = 5000; 
  
          #region Private Fields
         // RijndaelManaged aes; old version
          AesManaged aes;
          int IVLength = KeyLengthInBytes &gt;&gt; 1;
          #endregion Private Fields
  
          #region Internal Constructors
  
          internal SymmetricCryptor( )
          {
  
              aes = new AesManaged
              {
                  Mode = CipherMode.CBC,
                  KeySize= KeyLengthInBytes&lt;&lt;3,
                  Padding = PaddingMode.PKCS7,
  
  
              };
              //aes.KeySize = KeyLengthInBytes &lt;&lt; 3;
              //aes.Padding = PaddingMode.Zeros; //PKCS7 can not be used with stream
          }
  
          #endregion Internal Constructors
  
          #region Public Methods
  
          public byte[] Decrypt(byte[] cryptedData, string password, IVMode ivmode)
          {
              using (MemoryStream ms = new MemoryStream(cryptedData))
              {
                  using (MemoryStream data = new MemoryStream())
                  {
                      Decrypt(ms, data, password,ivmode);
                      return data.ToArray();
                  }
              }
  
          }
  
  
          public void Encrypt(Stream data, Stream trgStream, string password, IVMode ivmode)
          {
  
              try
              {
  
                  var key = GetKey(password);
  
  
                var iv  = (ivmode == IVMode.Auto)
                    ?key.GetBytes(IVLength).Reverse().ToArray()
                    :                  new byte[IVLength];
  
                  var dc = aes.CreateEncryptor(key.GetBytes(KeyLengthInBytes), iv);
  
                  using (CryptoStream cryptor = new CryptoStream(trgStream, dc, CryptoStreamMode.Write))
                  {
  
                      data.CopyTo(cryptor);
                      cryptor.FlushFinalBlock();
                      cryptor.Close();
                  }
  
  
              }
              catch (Exception)
              {
                  throw new InvalidOperationException("Invalid password.");
              }
          }
  
  
          public void Decrypt(Stream cryptedData, Stream trgStream, string password, IVMode ivmode)
          {
  
  
               try
              {
  
                 var key= GetKey(password);
  
                 var iv = (ivmode == IVMode.Auto)
                   ? key.GetBytes(IVLength).Reverse().ToArray()
                   : new byte[IVLength];
                 var dc = aes.CreateDecryptor(key.GetBytes(KeyLengthInBytes),iv);
  
                      using (CryptoStream cryptor = new CryptoStream(cryptedData, dc, CryptoStreamMode.Read))
                      {
  
                          cryptor.CopyTo(trgStream);
  
                          cryptor.Close();
                      }
  
  
              }
              catch (Exception)
              {
                  throw new InvalidOperationException("Invalid password.");
              }
          }
  
          public byte[] Encrypt(byte[] data, string password, IVMode ivmode)
          {
              using (MemoryStream ms = new MemoryStream(data))
              {
                  using (MemoryStream cData = new MemoryStream())
                  {
                      Encrypt(ms, cData, password,ivmode);
                      return cData.ToArray();
                  }
              }
          }
  
          #endregion Public Methods
  
          #region Private Methods
  
          private Rfc2898DeriveBytes GetKey(string password)
          {
              try
              {
                  var iv =
                      CompanyName.Framework.Cryptography.Digest.SHA1.Compute(password);
  
                  return new Rfc2898DeriveBytes(password, iv, Iterations);
  
  
              }
              catch (Exception)
              {
                  throw;
              }
          }
  
          #endregion Private Methods
  
  
      }
  }
  </code></pre>
  
  <p>My Android Cryptor, which tries to decrypt a message encrypted by the above C Sharp Cryptor looks like this, I tried to copy the Decrypt method of the C Sharp Cryptor:</p>
  
  <pre><code>public class Cryptor {
  
  private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
  private static final String AES = "AES";
  private static final String RANDOM_ALGO = "SHA1PRNG";
  private static final int KEY_LENGTH_IN_BITS = 256;
  private static final int IV_LENGTH = 16;
  private static final int PBE_ITERATION_COUNT = 5000;
  private static final int PBE_SALT_LENGTH_INT_BITS = 128;
  private static final String PBE_ALGO = "PBKDF2WithHmacSHA1";
  
  
  public static byte[] generateKeyFromPassword(String password, int Size) throws GeneralSecurityException {
      byte[] salt = generateSalt();
      KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, PBE_ITERATION_COUNT, Size);
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBE_ALGO);
      byte[] data = keyFactory.generateSecret(keySpec).getEncoded();
      return data;
  }
  
  private static byte[] generateSalt() throws GeneralSecurityException {
      return randomBytes(PBE_SALT_LENGTH_INT_BITS);
  }
  
  private static byte[] randomBytes(int length) throws GeneralSecurityException {
      SecureRandom random = SecureRandom.getInstance(RANDOM_ALGO);
      byte[] b = new byte[length];
      random.nextBytes(b);
      return b;
  }
  
  public static byte[] decrypt(byte[] cipherText, String password) throws GeneralSecurityException {
      byte[] keyBytes = generateKeyFromPassword(password, 256);
      byte[] ivBytes = generateKeyFromPassword(password, 128);
  
  
      Cipher cipher = Cipher.getInstance(TRANSFORMATION);
  
      ivBytes = reverse(ivBytes);
  
      SecretKeySpec secretKey = new SecretKeySpec(keyBytes, AES);
      IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
  
      cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
  
      byte[] decrypted = cipher.doFinal(cipherText);
      return decrypted;
  }
  
  
  public static byte[] reverse(byte[] array) {
      if (array == null) {
          return null;
      }
      int i = 0;
      int j = array.length - 1;
      byte tmp;
      while (j &gt; i) {
          tmp = array[j];
          array[j] = array[i];
          array[i] = tmp;
          j--;
          i++;
      }
      return array;
  }
  </code></pre>
  
  <p>But it is not working, When do final is called I get a </p>
  
  <pre><code>javax.crypto.BadPaddingException: error:1e06b065:Cipher functions:EVP_DecryptFinal_ex:BAD_DECRYPT
  </code></pre>
  
  <p>Exception. I am not sure what I am doing wrong, because my Decrypt Method in Android is doing the exact same thing as the Decrypt Method in C Sharp: First I generate a Key from the password, which is shared by the Csharp Server and me. Then I generate a random 128 bit IV, reversing it is not necessary, but C Sharp implementation reverses it, so I do it as well. Can anyone tell me what I am doing wrong? Here is the context where I use the Cryptor:</p>
  
  <pre><code>//open the client channel, read and return the response as byte[]
  Channel clientChannel = new Channel(serverAddress);
  byte[] result = clientChannel.execute(serviceID.toString(), data);
  
  //result[] is encrypted data. firstTen is the shared Password
  byte[] decrypted = Cryptor.decrypt(result, firstTen);
  </code></pre>
  
  <p>Server returns the result as Base64 encrypted, before passing it for decryption I get the result[] array through:
  It comes as a Base64 String. I get  the result[] array through:</p>
  
  <pre><code>Base64.decode(result, Base64.NO_WRAP);
  </code></pre>