Encrypting images using AES in Android with Kotlin + Glide + RxJava2

Umair Adil
Embrace-It
Published in
2 min readJan 19, 2019

Encryption & decryption are one of the most widely used features in today’s apps but still as a developer we struggle a lot on developing the right solution for it. It has become the basic requirement for any application that stores user’s sensitive data. Keeping images without file extensions, within cache or hidden storage isn’t secure enough, they can still be accessed with right tool and some Android knowledge.

My task was to save image as encrypted file as soon as it was captured from camera or downloaded from remote repository. Images had to be decrypted whenever they were to be shown to user in RecyclerView lists or when sending them back to server. This process needed to be chained together that’s why the best choice for implementation was to use RxJava2.

These are the required dependencies for this functionality.

Now let’s start with encryption part. To achieve image encryption we will need 128-Bit key. Let’s create that key.

Here is code for encrypting images.

We will encrypt some images using this method.

//Encrypt Image
ImageCrypter.encryptImage(fileToEncrypt)
.subscribeBy(
onNext = {
//Do something here

},
onError = {
it
.printStackTrace()
}
)

And here is code for decryption:

We can call decryption method like this:

ImageCrypter.decryptImage(pathOfEncryptedImage)
.subscribeBy(
onNext = {
//Do Something here
}
,
onError = {
it
.printStackTrace()
}
)

Encryption & decryption of any file can be achieved by using above methods, but when dealing with images, it’s a little bit tricky, because images have to be decrypted before previewing in ImageView.

So when we load images in Glide we use Glide’s callbacks. When image is successfully loaded in Glide, we delete it immediately. This process will repeat every time we load image. This will make sure that only encrypted copies exist in storage path. On top of it, we can even clear all files with ‘temp_’ tag to delete when app exits.

Encrypted Image will be saved with original name:

image_1.jpg

Decrypted Image will be saved with ‘temp’ TAG:

temp_image_1.jpg

Here is code for loading image using Glide:

ImageCrypter.decryptImage(path)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onNext = { decryptedFile ->

//Load image with delay
Observable.timer(500, TimeUnit.MILLISECONDS)
.doOnNext {
(context as Activity).runOnUiThread {
loadImageIntoImageView(imageView, decryptedFile.path, context)
}
}
.doOnError {
it
.printStackTrace()
}.subscribe()

},
onError = {
}
)
private fun loadImageIntoImageView(
imageView: ImageView,
path: String,
context: Context
) {

//Load image
GlideApp.with(context)
.load(path)
.apply(
RequestOptions
.skipMemoryCacheOf(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {

e?.printStackTrace()
return false
}

override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {

//Delete file after delay
deleteFileAfterView(path)

return false
}
})
.into(imageView)
}

That’s It. You can find complete code here:

--

--

Umair Adil
Embrace-It

Full Stack Developer | AI Enthusiast | Creative Content Creator