When working with files in your android app one of the most important aspects that you should consider is security, especially if you don’t want these files to be accessed from outside your app, storing files in your app’s specific storage will prevent other apps from accessing them but in rooted devices these files can still be accessed by other apps, and because the app specific storage is only encrypted by default in Android 10 and higher devices, and only 8.2% of devices run Android 10 (by the time i wrote this article), we will learn how to encrypt files starting from Android 6.0 using the security library that’s part of Android Jetpack.
Note: there is a version of the security library that supports Android 5.0 (API 21) and higher but its still in alpha stage you can check it out here
//Androidx security, get latest version here:https://developer.android.com/jetpack/androidx/releases/security implementation("androidx.security:security-crypto:1.0.0")
Creating an encrypted file:
First we’ll generate an encryption key for our app to use when encrypting / decrypting files, the key will be generated by the MasterKeys class, to generate keys the MasterKeys class uses a basic AES256-GCM key which is generated and stored in the AndroidKeyStore. The AndroidKeyStore is a container used to store cryptographic keys in the TEE or StrongBox.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
In this tutorial we will use AES256-GCM_SPEC specifications for encryption, which is the recommended for general use cases and well known for low latency and a minimum operation overhead on modern devices.
Next we’ll create the encrypted file using our new master key:
val file = File(context.cacheDir, "my-secret-file") val encryptedFile = EncryptedFile.Builder( file, context, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build()
our file with the name “my-secret-file” is now created in our app’s cache directory, now lets open an output stream and start writing data to our file.
Writing and reading data:
To start writing data we’ll create an output stream, this is the same FileOutputStream from the java.io package so this can be done in many ways but we’ll use the write method that takes a ByteArray in our example
val fileOutput = encryptedFile.openFileOutput() val data = "tahaben.com.ly is so cool!" val dataBytes = data.toByteArray() fileOutput.write(dataBytes) fileOutput.flush() fileOutput.close()
to decrypt the data from the encrypted file we simply create an input stream using the openFileInput method and read the bytes from the stream
val inputStream = encryptedFile.openFileInput() val decryptedBytes = inputStream.readBytes() inputStream.close() val mySecret = String(decryptedBytes) print(mySecret)
That’s it thanks for reading ! please feel free to post your questions or suggestions to improve the article in the comments.
If you’d like to see a more detailed example using the security library to encrypt files and shared preferences check out the Sample app FileLocker .