I'm a beginner working on AES encryption of images in android. So basically, I'm capturing images from the camera intent and encrypting those images and storing them in the file system as .jpg files.
The issue is that the entire encryption decryption mechanism seems to work fine on the first launch of the application.
I could see the images in broken form in the file system and the same images are properly visible in the emulator after decrypting those images and setting them to the ImageView.
The entire app flow seems to work perfectly on the first launch.
Once we kill the application and relaunch them, this time the app is suppose to pull out the encrypted images stored in the file system and decrypt them and show them in a list adapter. But instead The images are not visible.
Upon debugging, I got javax.crypto.BadPaddingException: pad block corrupted.
Please have a look at the code here:
import android.util.Base64;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class LocalFilesEncryptionAndDecryptionMechanism {
private static SecretKey secretKey;
private static byte[] IV = new byte[16];
private static KeyGenerator keyGenerator;
private static SecureRandom random;
private static Cipher cipher;
private static SecretKeySpec keySpec;
private static IvParameterSpec ivSpec;
private static String key = "lzk9rcgxnH8Ah2p1iL7LTB7DE9/N3+rQqMaPCwfRyoxzoWGECiy6E2euV/6qnQ1AVrMpJStDFDd1jJsvwxvhFG2tkJOjtWr3dYANDc/bEWhKL5YI6kKz6pSclJvnN8sO";
public static void initializeEncryption(){
try {
keyGenerator = KeyGenerator.getInstance("AES");
secretKey = keyGenerator.generateKey();
cipher = Cipher.getInstance("AES");
ivSpec = new IvParameterSpec(IV);
random = new SecureRandom();
random.setSeed(key.getBytes(StandardCharsets.UTF_8));
random.nextBytes(IV);
keyGenerator.init(256,random);
keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(byte[] plaintext) throws Exception {
// Cipher cipher = Cipher.getInstance("AES");
// keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES/ECB/PKCS5Padding");
// IvParameterSpec ivSpec = new IvParameterSpec(IV);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(plaintext);
return encrypted;
}
public static byte[] decrypt(byte[] encrypted) throws Exception {
// Cipher cipher = Cipher.getInstance("AES");
// keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES/ECB/PKCS5Padding");
// IvParameterSpec ivSpec = new IvParameterSpec(IV);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
//
// cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static byte[] readAllBytes(FileInputStream inputStream) throws IOException {
final int bufLen = 4 * 0x400; // 4KB
// final int bufLen = 1024*1024;
byte[] buf = new byte[bufLen];
int readLen;
IOException exception = null;
try {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
outputStream.write(buf, 0, readLen);
return outputStream.toByteArray();
}
} catch (IOException e) {
exception = e;
throw e;
} finally {
if (exception == null) inputStream.close();
else try {
inputStream.close();
} catch (IOException e) {
exception.addSuppressed(e);
}
}
}
}
The below is how I'm saving the image:
String rootFolder = getString(R.string.thumbnail_images);
String folderPath = rootFolder + "/" + cameraPictureFolderName;
File week_Folder = getActivity()
.getExternalFilesDir(folderPath);
// File f1 = getActivity().getApplicationInfo().dataDir;
// File week_Folder = new File(getActivity().getApplicationInfo().dataDir , folderPath );
String filePath = week_Folder.getPath() + "/"
+ cameraPictureFileName;
File final_file = new File(filePath);
FileOutputStream fo;
try {
saveToInternalStorage(BM,rootFolder,cameraPictureFolderName,cameraPictureFileName);
fo = new FileOutputStream(final_file);
byte[] encryptedBytes = LocalFilesEncryptionAndDecryptionMechanism.encrypt(bytes.toByteArray());
fo.write(encryptedBytes);
fo.flush();
fo.close();
}
private String saveToInternalStorage(Bitmap bitmapImage,String rootFolder,String cameraPictureFolderName, String imgName){
ContextWrapper cw = new ContextWrapper(getActivity().getApplicationContext());
final File directory = new File(getActivity().getFilesDir() + File.separator+ rootFolder +File.separator + cameraPictureFolderName);
// File directory = new File(getActivity().getFilesDir(), cameraPictureFolderName); //Getting a file within the dir.
if(! directory.exists()){
directory.mkdirs();
}
File mypath=new File(directory,imgName);
ByteArrayOutputStream fos = null;
try {
fos = new ByteArrayOutputStream();
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
byte[] encryptedImage = LocalFilesEncryptionAndDecryptionMechanism.encrypt(fos.toByteArray());
fos.reset();
fos.write(encryptedImage);
FileOutputStream imageOutputStream = new FileOutputStream(mypath);
imageOutputStream.write(encryptedImage);
imageOutputStream.flush();
imageOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return mypath.getAbsolutePath();
}
The below is the code I'm using to decrypt and load the images into adapter:
File imageFile = new File(context.getFilesDir()+ "/"+folderPath + "/"+ imageNameArray[position]);
try {
FileInputStream fileInputStream = new FileInputStream(imageFile);
encryptedBytes = LocalFilesEncryptionAndDecryptionMechanism.readAllBytes(fileInputStream);
// encryptedBytes = LocalFilesEncryptionAndDecryptionMechanism.encrypt(encryptedBytes);
decryptedBytes = LocalFilesEncryptionAndDecryptionMechanism.decrypt(encryptedBytes);
b = BitmapFactory.decodeByteArray(decryptedBytes,0,decryptedBytes.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
imageItem.setImageBitmap(b);
I get a pad block exception on second launch.
Can anyone please help me fix this issue?
Thank you very much in advance.