Encrypted Storage — Android

shivakumar
3 min readFeb 8, 2024

--

In this blog we will learn how to implement/use encryption to save local data in Android.

Introduction

Encryption is the process of encoding all user data on an Android device using symmetric encryption keys. Once a device is encrypted, all user-created data is automatically encrypted before committing it to disk and all reads automatically decrypt data before returning it to the calling process. Encryption ensures that even if an unauthorized party tries to access the data, they won’t be able to read it.

We will look into file-based encryption.

Getting Started

TL;DR — Refer github-link to install/use the library as is. Add dependency and jitpack base url also as library is hosted in JitPack. Brief Explanation of the usage is also available.

dependencies {
implementation 'com.github.shiva-kumar-R:encryptedstorage:Tag'
}

Here, we will deep dive into the process.

Explanation

Cipher is data class with which the configuration for the library can be made possible.

var algorithm: String = KeyProperties.KEY_ALGORITHM_AES,
var blockMode: String = KeyProperties.BLOCK_MODE_CBC,
var padding: String = KeyProperties.ENCRYPTION_PADDING_PKCS7

Cipher takes 3 parameters algorithm, blockmode and padding which configurable. Using these parameters encryption strategy can be modified if needed. By-default, AES encryption with CBC block mode and PKCS7 padding is applied.

Crypto-manager has the main implementation for encryption and decryption logic.

On setup we initialize algorithm from our cipher class. We have encrypt and decrypt methods.

encrypt takes InputbyteArray and OutputStream and returns encryptedByteArray. Data from file is passed as byteArray which is encrypted and pushed into file using outputStream.

decrypt takes the data from the file as byteStream and decrypts the data and returns new byteArray.

Android keystore is where the secret key is maintained. key is added as an entry the first time and then followin reads the same key is fetched and used.

Usage

Library can be used for 2 types of data encryption.

  1. Normal file encryption
  2. Preferences datastore

File Encryption

So, if we want to encrypt an normal text file which will be saved locally in android device then it is pretty straight forward approach.

Steps need to followed is -

  1. Create a file.
  2. Convert the data ie string into byteArray
  3. Pass the byteArray and new file to encrypt function in crypto module.
  4. That’s it.
cryptoManager.encrypt(bytes, fos)

Decryption is the reversal process.

cryptoManager.decrypt(FileInputStream(file))

Preferences Datastore

Good thing about datastore is it uses key-value pairs so, only serializer needs to be added on top of normal encryption.

While creating the datastore, pass the data class serializer as a parameter to dataStore. Serializer takes crypto as parameter. This serializer is from dataStore library not from java module.

private val Context.dataStore by dataStore(
fileName = "usersettings.json",
serializer = UserSettingSerializer(CryptoManagerImpl())
)

So, if dataclass extends serializer it has to override readFrom and writeTo methods. Using these you can encode and decode from custom data class to file store and also encrypt/decrypt during the process.

override suspend fun readFrom(input: InputStream): UserSettings {
val decryptedBytes = cryptoManager.decrypt(
inputStream = input
)
return try {
Json.decodeFromString(
deserializer = UserSettings.serializer(),
string = decryptedBytes.decodeToString()
)
} catch (e: SerializationException) {
e.printStackTrace()
defaultValue
}
}

override suspend fun writeTo(t: UserSettings, output: OutputStream) {
val data = Json.encodeToString(
serializer = UserSettings.serializer(),
value = t
)
cryptoManager.encrypt(
byteArray = data.encodeToByteArray(),
outputStream = output
)
}

That’s all for now. Thanks.

Please feel free to reach out to me on LinkedIn.

If you liked this blog, don’t forget to hit the 👏 .

--

--

No responses yet