DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

Encrypted Storage Guide - EncryptedSharedPreferences & KeyStore

Encrypted Storage Guide - EncryptedSharedPreferences & KeyStore

Secure sensitive data using encryption. EncryptedSharedPreferences provides transparent encryption.

Dependencies

dependencies {
    implementation("androidx.security:security-crypto:1.1.0-alpha06")
}
Enter fullscreen mode Exit fullscreen mode

EncryptedSharedPreferences Setup

class SecurePreferencesRepository(context: Context) {
    private val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()

    private val encryptedPreferences = EncryptedSharedPreferences.create(
        context,
        "secret_prefs",
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )

    fun savePassword(password: String) {
        encryptedPreferences.edit().putString("password", password).apply()
    }

    fun getPassword(): String? = encryptedPreferences.getString("password", null)
}
Enter fullscreen mode Exit fullscreen mode

EncryptedFile for Sensitive Files

class SecureFileRepository(context: Context) {
    private val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()

    fun writeSecureFile(filename: String, content: String) {
        val file = File(context.filesDir, filename)
        val encryptedFile = EncryptedFile.Builder(
            context,
            file,
            masterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        ).build()

        encryptedFile.openFileOutput().use { output ->
            output.write(content.toByteArray())
        }
    }

    fun readSecureFile(filename: String): String {
        val file = File(context.filesDir, filename)
        val encryptedFile = EncryptedFile.Builder(
            context,
            file,
            masterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        ).build()

        return encryptedFile.openFileInput().use { input ->
            input.bufferedReader().readText()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Using with DataStore

val Context.encryptedDataStore by preferencesDataStore(
    name = "encrypted_settings",
    corruptionHandler = ReplaceFileCorruptionHandler { emptyPreferences() }
)
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Use MasterKey for transparent encryption
  • Store API keys and tokens encrypted
  • Never commit unencrypted secrets
  • Use GCM mode for authenticated encryption

8 Android app templates on Gumroad

Top comments (0)