๐Ÿ” Android Security and Privacy

Encrypted Data Storage in Android

Android already encrypts user data at the device level, but app-level encryption adds protection for specific sensitive data against backups, extraction and some compromised-device scenarios. Here's what to encrypt, the modern tools to do it with, and how to migrate off deprecated libraries.

โœ๏ธ Yunok Tech ๐Ÿ“… Updated โฑ 3 min read ๐ŸŽฏ Intermediate
On this page
  1. What to encrypt at the app level
  2. About EncryptedSharedPreferences and EncryptedFile
  3. Encrypting files with Tink
  4. Encrypting a Room database
  5. Practices
  6. Examples
  7. Frequently asked questions
  8. Conclusion

Modern Android devices use file-based encryption: data at rest is encrypted, and apps' private directories are protected by the sandbox. So why encrypt again? Because device encryption protects a powered-off, locked device, not your app's data from backups, debugging tools on compromised devices, or another layer of defence your compliance team requires.

What to encrypt at the app level

DataEncrypt?Notes
Auth tokens, session secretsYesSee Secure Token Storage
Health, financial, identity documentsYesOften required by policy or regulation
Private user content (journals, private notes)OftenConsider user expectations
Cached public content, preferences like themeNoEncryption adds cost without benefit
Encryption tools for different storage types A Keystore-wrapped master key protects Tink keysets. Tink AEAD encrypts small values for DataStore; Tink streaming AEAD encrypts files; SQLCipher encrypts entire Room databases with a key protected by the Keystore. Keystore master key Small valuesTink AEAD โ†’ DataStore FilesTink streaming AEAD DatabasesSQLCipher + Room
One Keystore-protected root, with the right tool for each storage type.

About EncryptedSharedPreferences and EncryptedFile

Jetpack Security (androidx.security:security-crypto), which provided EncryptedSharedPreferences and EncryptedFile, has been deprecated. Existing apps keep working, but new code should use alternatives such as Tink directly (which security-crypto used internally), together with DataStore or files. Plan a migration that reads old values once and re-writes them with the new mechanism.

Encrypting files with Tink

EncryptedFiles.ktKotlin
object EncryptedFiles {
    private fun streamingAead(context: Context): StreamingAead {
        StreamingAeadConfig.register()
        return AndroidKeysetManager.Builder()
            .withSharedPref(context, "file_keyset", "file_keyset_prefs")
            .withKeyTemplate(KeyTemplates.get("AES256_GCM_HKDF_4KB"))
            .withMasterKeyUri("android-keystore://file_master_key")
            .build()
            .keysetHandle
            .getPrimitive(RegistryConfiguration.get(), StreamingAead::class.java)
    }

    fun write(context: Context, file: File, bytes: ByteArray) {
        val aad = file.name.toByteArray()               // bind ciphertext to the file name
        FileOutputStream(file).use { out ->
            streamingAead(context).newEncryptingStream(out, aad).use { it.write(bytes) }
        }
    }

    fun read(context: Context, file: File): ByteArray {
        val aad = file.name.toByteArray()
        return FileInputStream(file).use { input ->
            streamingAead(context).newDecryptingStream(input, aad).use { it.readBytes() }
        }
    }
}

In production, create the primitive once and reuse it. For small values, use Tink's Aead with a DataStore serializer, as shown in Secure Token Storage.

Encrypting a Room database

Room doesn't encrypt by itself. A common approach is SQLCipher, which plugs into Room through an openHelperFactory. Protect the database passphrase by generating random bytes and storing them encrypted with a Keystore-backed key:

Encrypted Room (outline)Kotlin
val passphrase: ByteArray = DbKeyProvider.getOrCreate(context)   // random 32 bytes, stored Tink/Keystore-encrypted
val factory = SupportOpenHelperFactory(passphrase)                // from the SQLCipher Android library
val db = Room.databaseBuilder(context, AppDatabase::class.java, "secure.db")
    .openHelperFactory(factory)
    .build()

Check the SQLCipher library's current artifact and class names, and measure the performance impact on your queries.

Practices

  • Use authenticated encryption (AES-GCM / AEAD), never ECB or unauthenticated modes.
  • Never hard-code keys, and never derive keys from constants in the APK.
  • Exclude encrypted data and keysets from backups, since Keystore keys don't restore.
  • Handle key loss: treat undecryptable data as missing, and re-sync or sign out.
  • Encrypt only what needs it, because encryption costs CPU and complexity.

Examples

Health diary

Room with SQLCipher, biometric lock on open, and no cloud backup of the database.

Document wallet

PDFs encrypted with Tink streaming AEAD, plus FLAG_SECURE on the viewer.

Banking session

Tokens via Tink AEAD in DataStore, cleared on logout.

Frequently asked questions

Is device encryption enough?

For low-sensitivity data, usually yes. For secrets and regulated data, app-level encryption adds protection for backups and some compromised-device scenarios.

Does encryption slow my app?

Some, especially for large files or databases. Measure, and encrypt selectively.

Can I use the deprecated library a bit longer?

Existing code continues to function, but it won't get updates. Plan migration rather than adding new usage.

Conclusion

Encrypt sensitive data at the app level with Keystore-protected keys: Tink AEAD for small values, streaming AEAD for files, and SQLCipher for databases. Migrate off the deprecated EncryptedSharedPreferences, exclude secrets from backup, and handle key loss gracefully.

Next step: limit what you collect in the first place with Android Permissions and Privacy Best Practices.

Official references

๐Ÿ“ฑ Apps built by Yunok Tech

Real Android apps on Google Play, free to download.

See all our apps โ†’

Ready to build real Android applications?

Security is easiest to get right when it is part of how you build from the first screen. Strengthen the Android fundamentals that secure, privacy-respecting apps are built on.

Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.

Explore the Android course and take your next step as an Android developer.

Share: LinkedIn X / Twitter WhatsApp