title: Facebook Conceal - Image Encryption and Decryption
body: <p>I am trying to encrypt and decrypt image using Facebook Conceal Library. This is the first time i am using it and hence bear with me if its trivial. I have looked at other questions on SO to figure out the reasons for my exceptions, my i couldn't  get it working.</p>
  
  <p>Here is what I have done till now...</p>
  
  <p>Integrating: I am using Eclipse and hence, downloaded crypto.jar and libs.zip from <a href="http://facebook.github.io/conceal/documentation/" rel="nofollow">here</a> and added the jar file to libs folder and .so files to respective folder inside libs folder.</p>
  
  <p>My scenario:</p>
  
  <p>I have to capture an image from camera, encrypt and store it on my phone memory. Decrypt it and show it in an imageview. At a later stage, i also need to decrypt this image from the memory and send it over network.</p>
  
  <p>So, my code goes as below...</p>
  
  <pre><code>@Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  
      if (Const.DEBUGGING) {
          Log.d(Const.DEBUG, "RequestCode: " + requestCode + "\nResultCode:"
                  + resultCode);
      }
  
      int tag = getRecordCount();
      tag++;
  
      if (requestCode == KTP_PICTURE_REQUEST_CODE) {
          if (resultCode == RESULT_OK) {
  
              ENCRYPTEDFILENAME = tag + "_" + KTP_TAG + ".png";
  
              saveFile((Bitmap) data.getExtras().get("data"), requestCode);
              Bitmap decryptedImage = decodeFile(ENCRYPTEDFILENAME);
              mImgBtnKtppicture.setImageBitmap(decryptedImage);
  
          } else if (resultCode == RESULT_CANCELED) {
              if (Const.DEBUGGING)
                  Log.d(Const.DEBUG, "KTP_RESULT CANCELED");
          } else {
  
          }
      }
  
      if (requestCode == PROFILE_PICTURE_REQUEST_CODE) {
  
          if (resultCode == RESULT_OK) {
  
              ENCRYPTEDFILENAME = tag + "_" + PROFILE_TAG + ".png";
  
              saveFile((Bitmap) data.getExtras().get("data"), requestCode);
              Bitmap decryptedImage = decodeFile(ENCRYPTEDFILENAME);
              mImgBtnPicture.setImageBitmap(decryptedImage);
  
          } else if (resultCode == RESULT_CANCELED) {
              if (Const.DEBUGGING)
                  Log.d(Const.DEBUG, "PICTURE_RESULT CANCELED");
          } else {
  
          }
  
      }
  }
  </code></pre>
  
  <p>SaveFile():</p>
  
  <pre><code>public void saveFile(Bitmap photo, int code) {
  
      try {
          ContextWrapper cw = new ContextWrapper(getApplicationContext());
          File directory = cw.getDir(DIRECTORY, Context.MODE_PRIVATE);
          File mypath = new File(directory, ENCRYPTEDFILENAME);
  
          if (code == KTP_PICTURE_REQUEST_CODE) {
              mKtppicture = Uri.fromFile(mypath).toString();
  
              if (Const.DEBUGGING)
                  Log.d(Const.DEBUG, "KTP Picture Path: " + mKtppicture);
          } else if (code == PROFILE_PICTURE_REQUEST_CODE) {
              mPicture = Uri.fromFile(mypath).toString();
  
              if (Const.DEBUGGING)
                  Log.d(Const.DEBUG, "Profile Picture Path: " + mPicture);
          }
  
  
          Crypto crypto = new Crypto(
                    new SharedPrefsBackedKeyChain(this),
                    new SystemNativeCryptoLibrary());
  
  
          if (!crypto.isAvailable()) {
                return;
              }
  
          OutputStream fileStream = new BufferedOutputStream(
                    new FileOutputStream(mypath));
  
          OutputStream outputStream = crypto.getCipherOutputStream(
                    fileStream, new Entity("Password"));
  
          ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
          objectOutputStream.write(bitmapToBytes(photo));
  
          objectOutputStream.close(); //Line with exception
      } catch (FileNotFoundException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }
  </code></pre>
  
  <p>bitmapToBytes():</p>
  
  <pre><code>private byte[] bitmapToBytes(Bitmap photo) {
  
      ByteArrayOutputStream stream = new ByteArrayOutputStream();
      photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
      byte[] byteArray = stream.toByteArray();
  
      return byteArray;
  }
  </code></pre>
  
  <p>decodeFile():</p>
  
  <pre><code>private Bitmap decodeFile(String filename) {
  
      Crypto crypto = new Crypto(
                new SharedPrefsBackedKeyChain(this),
                new SystemNativeCryptoLibrary());
  
      ContextWrapper cw = new ContextWrapper(getApplicationContext());
      File directory = cw.getDir(DIRECTORY, Context.MODE_PRIVATE);
      File file = new File(directory, filename);
  
      try{
          FileInputStream fileStream = new FileInputStream(file);
          InputStream inputStream = crypto.getCipherInputStream(
                    fileStream,
                    new Entity("Password"));
          ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
          Bitmap bitmap = bytesToBitmap((byte[])objectInputStream.readObject());
  
          return bitmap;
      }catch (Exception e) {
          e.printStackTrace();
      }
  
      return null;
  }
  </code></pre>
  
  <p>bytesToBitmap():</p>
  
  <pre><code>private Bitmap bytesToBitmap(byte[] bytes) {
  
      Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
      return bitmap;
  }
  </code></pre>
  
  <p>When i try to save the image, i get a UnsupportedOperationException at <code>objectOutputStream.close();</code> in saveFile()</p>
  
  <p>Logcat Trace:</p>
  
  <pre><code>10-01 16:55:34.529: W/System.err(31291): java.lang.UnsupportedOperationException
  10-01 16:55:34.529: W/System.err(31291):    at com.facebook.crypto.streams.NativeGCMCipherOutputStream.write(NativeGCMCipherOutputStream.java:93)
  10-01 16:55:34.529: W/System.err(31291):    at java.io.DataOutputStream.writeByte(DataOutputStream.java:144)
  10-01 16:55:34.529: W/System.err(31291):    at java.io.ObjectOutputStream.drain(ObjectOutputStream.java:394)
  10-01 16:55:34.529: W/System.err(31291):    at java.io.ObjectOutputStream.flush(ObjectOutputStream.java:461)
  10-01 16:55:34.529: W/System.err(31291):    at java.io.ObjectOutputStream.close(ObjectOutputStream.java:337)
  10-01 16:55:34.529: W/System.err(31291):    at com.xx.xxx.RegistrationActivity.saveFile(RegistrationActivity.java:761)
  10-01 16:55:34.529: W/System.err(31291):    at com.xx.xxx.RegistrationActivity.onActivityResult(RegistrationActivity.java:639)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.Activity.dispatchActivityResult(Activity.java:5423)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.ActivityThread.access$1300(ActivityThread.java:135)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
  10-01 16:55:34.529: W/System.err(31291):    at android.os.Handler.dispatchMessage(Handler.java:102)
  10-01 16:55:34.529: W/System.err(31291):    at android.os.Looper.loop(Looper.java:136)
  10-01 16:55:34.529: W/System.err(31291):    at android.app.ActivityThread.main(ActivityThread.java:5001)
  10-01 16:55:34.529: W/System.err(31291):    at java.lang.reflect.Method.invokeNative(Native Method)
  10-01 16:55:34.529: W/System.err(31291):    at java.lang.reflect.Method.invoke(Method.java:515)
  10-01 16:55:34.529: W/System.err(31291):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
  10-01 16:55:34.529: W/System.err(31291):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
  10-01 16:55:34.529: W/System.err(31291):    at dalvik.system.NativeStart.main(Native Method)
  10-01 16:55:34.529: W/System.err(31291): java.io.IOException: Unexpected crypto version -1
  10-01 16:55:34.529: W/System.err(31291):    at com.facebook.crypto.util.Assertions.checkArgumentForIO(Assertions.java:29)
  10-01 16:55:34.539: W/System.err(31291):    at com.facebook.crypto.CipherHelper.getCipherInputStream(CipherHelper.java:52)
  10-01 16:55:34.539: W/System.err(31291):    at com.facebook.crypto.Crypto.getCipherInputStream(Crypto.java:83)
  10-01 16:55:34.539: W/System.err(31291):    at com.xx.xxx.RegistrationActivity.decodeFile(RegistrationActivity.java:821)
  10-01 16:55:34.539: W/System.err(31291):    at com.xx.xxx.RegistrationActivity.onActivityResult(RegistrationActivity.java:640)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.Activity.dispatchActivityResult(Activity.java:5423)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.ActivityThread.access$1300(ActivityThread.java:135)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
  10-01 16:55:34.539: W/System.err(31291):    at android.os.Handler.dispatchMessage(Handler.java:102)
  10-01 16:55:34.539: W/System.err(31291):    at android.os.Looper.loop(Looper.java:136)
  10-01 16:55:34.539: W/System.err(31291):    at android.app.ActivityThread.main(ActivityThread.java:5001)
  10-01 16:55:34.539: W/System.err(31291):    at java.lang.reflect.Method.invokeNative(Native Method)
  10-01 16:55:34.539: W/System.err(31291):    at java.lang.reflect.Method.invoke(Method.java:515)
  10-01 16:55:34.539: W/System.err(31291):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
  10-01 16:55:34.549: W/System.err(31291):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
  10-01 16:55:34.549: W/System.err(31291):    at dalvik.system.NativeStart.main(Native Method)
  10-01 16:55:34.549: D/BAT(31291): onResume called
  </code></pre>
  
  <p>Thanks for your help...</p>