title: android AES decrypt files: BadPaddingException: EVP_CipherFinal_ex
body: <p>I am recently working on file encryption / decryption. </p>
  
  <p>BadPaddingException: EVP_CipherFinal_ex: always occurs when I try to decrypt the file with the same key. </p>
  
  <p>Code snippets will be posted below.</p>
  
  <p>Am I doing something wrong? </p>
  
  <p>thank you for your helps.</p>
  
  <p>Encrypt</p>
  
  <pre><code>public static void encryptFile() {
      File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + TARGET_FILE);
  
      FileInputStream fileInputStream;
      FileOutputStream fileOutputStream;
  
      byte[] buffer = new byte[1024 * 8];
  
      IvParameterSpec ivParameterSpec = new IvParameterSpec("1234567890123456".getBytes());
  
      byte[] key = "only for testing".getBytes();
      MessageDigest sha;
      try {
          sha = MessageDigest.getInstance("SHA-1");
          key = sha.digest(key);
      } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
      }
      key = Arrays.copyOf(key, 16); // use only first 128 bit
  
      SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
  
      try {
          fileInputStream = new FileInputStream(file);
          fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE);
  
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
          cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
  
          //CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher);
  
          int read;
  
          while ((read = fileInputStream.read(buffer)) &gt; 0) {
              Log.i(TAG, "encrypt read= " + read);
  
              byte[] encryptedData = cipher.doFinal(buffer);
              if (encryptedData != null) {
                  Log.i(TAG, "encrypted size= " + encryptedData.length);
                  fileOutputStream.write(encryptedData, 0, read);
              }
  
              //cipherOutputStream.write(buffer, 0, buffer.length);
          }
          //cipherOutputStream.flush();
          //cipherOutputStream.close();
          fileInputStream.close();
          fileOutputStream.close();
  
      } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException
              | IllegalBlockSizeException | BadPaddingException
              | InvalidAlgorithmParameterException | InvalidKeyException e) {
          e.printStackTrace();
      }
  }
  </code></pre>
  
  <p>Decrypt</p>
  
  <pre><code>public static void decryptFile() {
      File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE);
  
      FileInputStream fileInputStream;
      FileOutputStream fileOutputStream;
  
      byte[] buffer = new byte[1024 * 8];
  
      IvParameterSpec ivParameterSpec = new IvParameterSpec("1234567890123456".getBytes());
  
      byte[] key = "only for testing".getBytes();
      MessageDigest sha;
      try {
          sha = MessageDigest.getInstance("SHA-1");
          key = sha.digest(key);
      } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
      }
      key = Arrays.copyOf(key, 16); // use only first 128 bit
  
      SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
  
      try {
          fileInputStream = new FileInputStream(file);
          fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + DECRYPT_FILE);
  
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
          cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
  
          //CipherInputStream cipherInputStream = new CipherInputStream(fileInputStream, cipher);
  
          int read;
  
          while ((read = fileInputStream.read(buffer)) &gt; 0) {
              Log.i(TAG, "decrypt read= " + read);
  
              byte[] decryptedData = cipher.doFinal(buffer);
              if (decryptedData != null) {
                  Log.i(TAG, "decrypted size= " + decryptedData.length);
                  fileOutputStream.write(decryptedData, 0, read);
              }
  
              //fileOutputStream.write(buffer, 0, buffer.length);
          }
          fileOutputStream.flush();
          fileOutputStream.close();
          //cipherInputStream.close();
          fileInputStream.close();
  
      } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException
              | IllegalBlockSizeException | BadPaddingException
              | InvalidAlgorithmParameterException | InvalidKeyException e) {
          e.printStackTrace();
      }
  }
  </code></pre>
  
  <p>btw: It will work properly when I use CipherInputStream / CipherOutStream. I want to know if it is possible to use just FileInputStream / FileOutputStream only? thank you.</p>
  
  <p>Edited:
  Encrypt function will enlarge byte array about 16 bytes, I've tried increase the buffer size of decryption and still can't get it work.</p>
  
  <pre><code>byte[] buffer = new byte[1024 * 8 + 16];
  </code></pre>
  
  <p>Log:</p>
  
  <p>I/#_: decrypt read= 8208</p>
  
  <p>javax.crypto.BadPaddingException: EVP_CipherFinal_ex</p>
  
  <p>at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)</p>
  
  <p>at com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:430)</p>
  
  <p>at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:466)</p>
  
  <p>at javax.crypto.Cipher.doFinal(Cipher.java:1340)</p>
  
  <p>at CryptoHelper.decryptFile(CryptoHelper.java:128)</p>
  
  <p><strong>Edited</strong> Update code here based on #Robert's answer for anyone who encountered the same problems like I did.</p>
  
  <p>Encrypt:</p>
  
  <pre><code>int read;
  
          while ((read = fileInputStream.read(buffer)) &gt; 0) {
              Log.i(TAG, "encrypt read= " + read);
              byte[] encryptedData = cipher.update(buffer, 0, read);
              //byte[] encryptedData = cipher.doFinal(buffer);
              if (encryptedData != null) {
                  Log.i(TAG, "encrypted size= " + encryptedData.length);
                  fileOutputStream.write(encryptedData, 0, encryptedData.length);
              }
  
              //cipherOutputStream.write(buffer, 0, buffer.length);
          }
          byte[] finals = cipher.doFinal();
          Log.i(TAG, "encrypted finals = " + finals.length);
          fileOutputStream.write(finals, 0, finals.length);
  </code></pre>
  
  <p>Decrypt:</p>
  
  <pre><code>int read;
  
          while ((read = fileInputStream.read(buffer)) &gt; 0) {
              Log.i(TAG, "decrypt read= " + read);
  
              //byte[] decryptedData = cipher.doFinal(buffer);
              byte[] decryptedData = cipher.update(buffer, 0, read);
              if (decryptedData != null) {
                  Log.i(TAG, "decrypted size= " + decryptedData.length);
                  fileOutputStream.write(decryptedData, 0, decryptedData.length);
              }
  
              //fileOutputStream.write(buffer, 0, buffer.length);
          }
          byte[] finals = cipher.doFinal();
          Log.i(TAG, "decrypted finals = " + finals.length);
          fileOutputStream.write(finals, 0, finals.length);
  </code></pre>
  
  <p>Thanks again for Robert's help.</p>