Secure storage: Keystore, EncryptedSharedPreferences
The Android Keystore is a hardware-protected store for cryptographic keys: key material never enters the app process, and operations (signing, encryption) run in a secure environment (TEE or a StrongBox chip). Keys are non-exportable — even on a rooted device the key itself cannot be stolen.
Key capabilities:
setUserAuthenticationRequired(true)— using the key demands biometrics/PINsetInvalidatedByBiometricEnrollment(true)— enrolling a new fingerprint invalidates the key- StrongBox (on supporting devices) — a dedicated secure element chip
The practical layer: EncryptedSharedPreferences / EncryptedFile (Jetpack Security) — AES-256 encryption under a Keystore master key, with the familiar key-value interface.
What goes where: access/refresh tokens — encrypted storage; the PIN — never in plaintext, only salted-hashed or server-verified; the full card number (PAN) and CVV — never locally.
class SecureTokenStore(context: Context) {
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM) // açar Keystore-da
.build()
private val prefs = EncryptedSharedPreferences.create(
context,
"secure_tokens",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
fun saveRefreshToken(token: String) =
prefs.edit().putString("refresh_token", token).apply()
fun refreshToken(): String? = prefs.getString("refresh_token", null)
fun clear() = prefs.edit().clear().apply() // logout-da MÜTLƏQ
}Storing tokens with EncryptedSharedPreferences
Interview traps: (1) "what if we keep the token in BuildConfig/strings.xml?" — APKs decompile; both are plaintext; (2) "SharedPreferences is sandboxed anyway, what's the problem?" — root, backup extraction and other vectors can read it; the sandbox is a security layer, not encryption; (3) without allowBackup="false" or dataExtractionRules, unencrypted files can reach cloud backups. The Jetpack Security library's deprecation may come up — the concept (Keystore master key + AES) stands regardless.
🛠 Practice task
Token storage drill:
- Store a value in plain
SharedPreferences, then read it back in plaintext withadb shell run-as <package> cat shared_prefs/*.xml. - Store the same value with
EncryptedSharedPreferencesand confirm the file is now unreadable. - Check
allowBackupin the manifest and write the rule that excludes sensitive files from backups.
Done when: you can fill in the "what goes where" table for your own project.
📚 Sources and documentation
- Android Keystore systemofficialdeveloper.android.com
- Security guidelines for dataofficialdeveloper.android.com