user3303112
user3303112

Reputation: 11

JPEG bytes encryption returns bad image when the file is decrypted

I'm working on a simple code for encrypting the pixels of a JPEG image file. The code works well for encryption, generating a pseudo random image but when I try to decrypt it returns a not equals to original image. I'm using simple Cipher encryption (RC4).

public class MainActivity extends Activity {

static byte[] keyValue = {'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y'};

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ImageView imgView = (ImageView) findViewById(R.id.imageView1);

    Bitmap picture = getBitmapFromAsset("result.jpg");
    Bitmap resultPic = picture.copy(Bitmap.Config.ARGB_8888, true);
    picture.recycle();

    int width = resultPic.getWidth();
    int height = resultPic.getHeight();

    int[] pixels = new int[width * height];

    resultPic.getPixels(pixels, 0, width, 0, 0, width, height);

    //--------- perform encryption

    byte[] content = intArrToByteArr(pixels);

    try {

        content = decrypt(content);

    } catch (Exception e) { }

    pixels = byteArrToIntArr(content);

    //--------------------------------------------

    resultPic.setPixels(pixels, 0, width, 0, 0, width, height);

    imgView.setImageBitmap(resultPic);

    File file = new File(Environment.getExternalStorageDirectory().toString() + "/result.jpg");

    try {

        FileOutputStream fOut = new FileOutputStream(file);
        resultPic.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
        fOut.close();
    }
    catch (Exception e) { }
}

public static byte[] encrypt(byte[] Data) throws Exception {

    Key key = generateKey();
    Cipher c = Cipher.getInstance("RC4");
    c.init(Cipher.ENCRYPT_MODE, key);

    byte[] encVal = c.doFinal(Data);

    return encVal;
}

public static byte[] decrypt(byte[] encryptedData) throws Exception {

    Key key = generateKey();
    Cipher c = Cipher.getInstance("RC4");
    c.init(Cipher.DECRYPT_MODE, key);

    byte[] decValue = c.doFinal(encryptedData);

    return decValue;
}

private static Key generateKey() throws Exception {

    Key key = new SecretKeySpec(keyValue, "RC4");

    return key;
}

public static byte[] intArrToByteArr(int[] input){

    ByteBuffer byteBuffer = ByteBuffer.allocate(input.length * 4);
    IntBuffer intBuffer = byteBuffer.asIntBuffer();
    intBuffer.put(input);

    byte[] array = byteBuffer.array();

    return array;
}

public static int[] byteArrToIntArr(byte[] input){

    IntBuffer intBuf = ByteBuffer.wrap(input).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
    int[] array = new int[intBuf.remaining()];
    intBuf.get(array);

    return array;
}

private Bitmap getBitmapFromAsset(String strName) {

    AssetManager assetManager = getAssets();
    InputStream istr = null;

    try {

        istr = assetManager.open(strName);
    } catch (IOException e) { }

    Bitmap bitmap = BitmapFactory.decodeStream(istr);

    return bitmap;
}

}

Here's the normal jpeg file: http://postimg.org/image/m13xdbpi5/

Here's the encrypted one: http://postimg.org/image/dzsialsw1/

And here's the decrypted image: http://postimg.org/image/pm4pv01hb/

Upvotes: 0

Views: 1151

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1501646

You're encrypting, but then saving the result as a JPEG. That's a lossy format - after loading it again, you'll end up with an image which is visually similar to the original, but may well have some different pixels... which means it won't decrypt back to the original pixels.

You should check that you can encrypt/decrypt without re-encoding the values as an image. If that much works, then you know the encryption isn't the problem... but you'll still have the issue of losing information when you encode it as a JPEG...

Upvotes: 1

Related Questions