title: Correct way of Encrypting and Decrypting an Image using AES
body: <p>EDIT ::: The code in the question works, but it takes around 10 seconds for getting back to the activity once the image is taken in camera. I gave up this approach and used Facebook's Conceal Library to encrypt and decrypt images. Link to Facebook's Solution : <a href="https://stackoverflow.com/questions/26140389/facebook-conceal-image-encryption-and-decryption">Facebook Conceal - Image Encryption and Decryption</a></p>
  
  <hr>
  
  <p>I have looked at lot of examples, but still couldn't figure out a way to get Encryption and Decryption right. I thought i got it correct when I used some random code on the internet, but while decoding, i get a BadPadding Exception. </p>
  
  <p>So, i am trying to work it out. I am following the below question, as suggested by most people on SO (but this code shows how to encrypt a string). Can some one help me out in encrypting and decrypting the image? Will the code in the question work for images?</p>
  
  <p>Link to the question : <a href="https://stackoverflow.com/questions/992019/java-256-bit-aes-password-based-encryption/992413#992413">Java 256-bit AES Password-Based Encryption</a></p>
  
  <p>Here is what i have done till now:</p>
  
  <p>//Global arraylist to store iv and cipher</p>
  
  <pre><code>static ArrayList&lt;byte[]&gt; ivandcipher = new ArrayList&lt;byte[]&gt;();
  </code></pre>
  
  <p>//Generating Key</p>
  
  <pre><code>public static SecretKey generateKey() throws NoSuchAlgorithmException {
  
      char[] password = { 'a', 'b', 'c', 'd', 'e' };
      byte[] salt = { 1, 2, 3, 4, 5 };
  
      SecretKeyFactory factory = SecretKeyFactory
              .getInstance("PBKDF2WithHmacSHA1");
      KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
      SecretKey tmp = null;
      try {
          tmp = factory.generateSecret(spec);
      } catch (InvalidKeySpecException e) {
          e.printStackTrace();
      }
  
      yourKey = new SecretKeySpec(tmp.getEncoded(), "AES");
  
      return yourKey;
  }
  </code></pre>
  
  <p>//Encoding File</p>
  
  <p>//byte[] fileData, contains the bitmap(image) converted to byte[]</p>
  
  <pre><code>public static ArrayList&lt;byte[]&gt; encodeFile(SecretKey yourKey, byte[] fileData)
          throws Exception {
  
      byte[] encrypted = null;
  
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, yourKey);
      AlgorithmParameters params = cipher.getParameters();
      byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
      encrypted = cipher.doFinal(fileData);   
  
      ivandcipher.clear();
      ivandcipher.add(iv);
      ivandcipher.add(encrypted);
  
      return ivandcipher;
  }
  </code></pre>
  
  <p>Why am i adding iv and encrypted byte[]s to ivandcipher. Because, as the answer in the link suggests, that i should be using the same iv while decryption.</p>
  
  <p>//Decode file</p>
  
  <p>//I call a overloaded decodeFile method inside this method.. please note</p>
  
  <pre><code>private Bitmap decodeFile(String filename) {
  
      try {
          yourKey = generateKey();
      } catch (NoSuchAlgorithmException e1) {
          e1.printStackTrace();
      }
  
      try {
          byte[] decodedData = decodeFile(yourKey, readFile(filename));
          Bitmap bitmap = bytesToBitmap(decodedData);
  
          return bitmap;
      } catch (Exception e) {
          e.printStackTrace();
      }
  
      return null;
  }
  </code></pre>
  
  <p>//overloaded decodeFile method</p>
  
  <pre><code>public static byte[] decodeFile(SecretKey yourKey, byte[] fileData)
          throws Exception {
  
      byte[] decrypted = null;
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, yourKey, new IvParameterSpec(ivandcipher.get(0)));
      decrypted = cipher.doFinal(fileData);
      return decrypted;
  }
  </code></pre>
  
  <p>I guess the problem is with the fileData[], that i am not able to encrypt and decrypt correctly. For Strings as shown in the answer of the above link, i.e., </p>
  
  <p><code>byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));</code></p>
  
  <p>what should be given as parameter for cipher.doFinal()?</p>
  
  <p>Let me know if you need any other piece of code.</p>