EncryptedSharedPreferences — is een component van de AndroidX Security-bibliotheek die transparante versleuteling biedt van gegevens die via de SharedPreferences API worden opgeslagen. In tegenstelling tot gewone SharedPreferences, waar gegevens in een open XML-bestand worden opgeslagen, versleutelt EncryptedSharedPreferences automatisch sleutels en waarden voordat ze naar schijf worden geschreven. Volgens Android Developers gebruikt de bibliotheek AES-256 GCM voor waarden en AES-256 SIV (RFC 5297) voor sleutels, wat vertrouwelijkheid en integriteit van gegevens garandeert.
Belangrijkste punten
EncryptedSharedPreferences — is een klasse uit het pakket androidx.security.crypto, geïntroduceerd in AndroidX Security 1.0.0 (2019). Het implementeert de SharedPreferences-interface, maar alle schrijfbewerkingen (putString, putInt, putBoolean, enz.) versleutelen gegevens vooraf, en leesbewerkingen ontsleutelen ze voordat ze worden teruggegeven.
Standaard SharedPreferences slaat gegevens op in een XML-bestand in de app-directory (/data/data/package/shared_prefs/). Het bestand is niet versleuteld — bij root-toegang tot het apparaat of bij back-upanalyse worden alle gegevens als gewone XML gelezen. Authenticatietokens, API-sleutels, persoonlijke gebruikersgegevens worden toegankelijk voor een aanvaller.
EncryptedSharedPreferences lost dit probleem op bibliotheekniveau op: gegevens worden versleuteld voordat ze naar schijf worden geschreven en ontsleuteld bij het lezen. De ontwikkelaar hoeft geen cryptografische functies handmatig aan te roepen — de API blijft identiek aan gewone SharedPreferences.
De AndroidX Security bibliotheek v1.0.0 werd uitgebracht in december 2019. EncryptedSharedPreferences verving de verouderde aanpak met handmatige versleuteling via Cipher + SharedPreferences. De huidige stabiele versie is 1.1.0-alpha06 (2024), die API 19+ ondersteunt. De bibliotheek maakt deel uit van Jetpack en vereist geen extra machtigingen.
Volgens Google Security Blog (2024) is EncryptedSharedPreferences de aanbevolen methode voor het opslaan van vertrouwelijke app-instellingen die geen synchronisatie via de cloud nodig hebben. Voor complexere scenario's wordt Room met versleuteling via SQLCipher aanbevolen.
EncryptedSharedPreferences gebruikt een tweelaags versleutelingsschema: de hoofdsleutel (Master Key) wordt opgeslagen in Android Keystore en voor gegevensversleuteling worden afgeleide sleutels gebruikt. Dit is een combinatie van Keystore-bescherming en de prestaties van symmetrische versleuteling.
Voor waarden wordt AES-256 GCM (Galois/Counter Mode) gebruikt — een gemauthenticeerde versleutelingsmodus (AEAD) die vertrouwelijkheid en integriteit van gegevens biedt. Voor sleutels (parameternamen) wordt AES-256 SIV (RFC 5297) toegepast — deterministische versleuteling die nodig is om op sleutel te zoeken zonder de inhoud ervan prijs te geven.
Elk bestand EncryptedSharedPreferences bevat versleutelde sleutel-waardeparen. Bestandsstructuur: eerst een header met metadata (versie, sleutel-ID), dan een lijst met versleutelde items. Het bestand is geen geldige XML en is niet leesbaar in teksteditors.
De klasse MasterKey is verantwoordelijk voor het maken en beheren van de 256-bits hoofdsleutel die in Android Keystore wordt opgeslagen. MasterKey.Builder maakt configuratie mogelijk: opslagtype (Keystore of software), biometrische beveiliging, levensduur van de sleutel. Standaard wordt de hoofdsleutel gegenereerd in Android Keystore met AES/GCM/NoPadding-algoritme.
import androidx.security.crypto.MasterKey
import androidx.security.crypto.EncryptedSharedPreferences
fun getEncryptedPrefs() {
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.AES256_GCM_SPEC)
.build()
val prefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}
EncryptedSharedPreferences.create accepteert vijf parameters: context, bestandsnaam, hoofdsleutel, versleutelingsschema voor sleutels en versleutelingsschema voor waarden. De keuze van schema's beïnvloedt prestaties en beschermingsniveau.
AES256_SIV — deterministische versleuteling: identieke sleutels geven altijd dezelfde versleutelde tekst. Dit is nodig om op sleutel te zoeken (SharedPreferences.getX(key)). Nadeel: een aanvaller kan bepalen welke sleutels worden gebruikt op basis van herhalende versleutelde teksten. AES256_SIV2 — verbeterde versie met extra randomisatie.
Voor waarden wordt AES256_GCM gebruikt. GCM voegt een 12-byte IV (initialisatievector) en een 16-byte authenticatietag toe aan elke waarde. Dit garandeert vertrouwelijkheid (niemand kan de waarde lezen) en authenticatie (niemand kan de waarde wijzigen zonder detectie).
De methode setUserAuthenticationRequired(true) in MasterKey.Builder vereist biometrische bevestiging voordat de hoofdsleutel uit Keystore wordt verkregen. Dit voegt een extra laag toe: zelfs als de app op een ontgrendeld apparaat draait, kan een aanvaller EncryptedSharedPreferences niet lezen zonder Face ID of Touch ID.
Belangrijk: met setUserAuthenticationRequired wordt de hoofdsleutel ontoegankelijk als de gebruiker de biometrie heeft gewijzigd of verwijderd. KeyPermanentlyInvalidatedException moet worden afgehandeld en er moet een nieuwe hoofdsleutel worden gemaakt met gegevensmigratie.
fun createBiometricKey(): MasterKey {
return MasterKey.Builder(context)
.setKeyScheme(MasterKey.AES256_GCM_SPEC)
.setUserAuthenticationRequired(true)
.setRequestStrongBoxBacked(true)
.build()
}
fun writeSecureToken(token: String) {
try {
prefs.edit().putString("auth_token", token).apply()
} catch (e: KeyPermanentlyInvalidatedException) {
// Biometrie is veranderd — de sleutel moet opnieuw worden aangemaakt
}
}
Laten we een volledig voorbeeld bekijken van integratie van EncryptedSharedPreferences in een Android-app in Kotlin. De bibliotheek androidx.security:security-crypto wordt toegevoegd via Gradle.
Voeg in het bestand build.gradle (app) toe: implementation “androidx.security:security-crypto:1.1.0-alpha06”. Voor Kotlin-projecten is ook kotlin-stdlib vereist. Initialisatie van MasterKey gebeurt eenmalig, meestal in Application.onCreate of via een DI-container.
Na het maken van een EncryptedSharedPreferences-instantie verschilt de API niet van gewone SharedPreferences. edit() retourneert een Editor, alle methoden (putString, getString, putBoolean, getBoolean) werken analoog. Het verschil zit alleen binnenin: gegevens worden versleuteld bij schrijven en ontsleuteld bij lezen.
class AuthRepository(context: Context) {
private val prefs = createEncryptedPrefs(context)
fun saveCredentials(login: String, password: String) {
prefs.edit()
.putString("login", login)
.putString("password", password)
.apply()
}
fun getToken(): String? {
return prefs.getString("auth_token", null)
}
fun clearAll() {
prefs.edit().clear().apply()
}
}
Voor migratie van bestaande gegevens van onbeveiligde SharedPreferences naar EncryptedSharedPreferences moet u: alle gegevens uit het oude bestand lezen, een nieuwe EncryptedSharedPreferences maken, alle gegevens schrijven, het oude bestand verwijderen. Google biedt geen ingebouwde migratietool — de ontwikkelaar implementeert deze zelf.
De keuze tussen SharedPreferences en EncryptedSharedPreferences hangt af van het type opgeslagen gegevens. Voor instellingen van de interface (thema, taal, sortering) zijn gewone SharedPreferences voldoende. Voor vertrouwelijke informatie (tokens, wachtwoorden, sleutels) is EncryptedSharedPreferences verplicht.
EncryptedSharedPreferences is langzamer dan gewone vanwege cryptografische bewerkingen. Het schrijven van een enkele tekstwaarde duurt ~5-15 ms (afhankelijk van gegevensgrootte en hardwarematige AES-versnelling). Lezen — 2-5 ms. Voor de meeste apps is dit niet merkbaar, maar bij batchbewerkingen (migratie, herstel) is het beter apply() te gebruiken in plaats van commit().
Gewone SharedPreferences bieden geen enkele cryptografische bescherming: het XML-bestand wordt gelezen door elk proces met root-toegang of via adb backup. EncryptedSharedPreferences versleutelt gegevens op app-niveau en de hoofdsleutel wordt opgeslagen in Android Keystore met mogelijkheid tot hardwarematige beveiliging (StrongBox).
| Kenmerk | SharedPreferences | EncryptedSharedPreferences |
|---|---|---|
| Opslag | Open XML | Versleuteld binair bestand |
| Versleuteling | Nee | AES-256 GCM + SIV |
| Sleutelbeveiliging | Nee | Android Keystore + StrongBox |
| Prestaties | 0.1-1 ms | 2-15 ms |
| Aanbeveling | UI-instellingen | Tokens, sleutels, PII |
Gebruik EncryptedSharedPreferences voor het opslaan van: OAuth refresh token, API-sleutels voor externe services, e-mail of telefoonnummer van de gebruiker, vertrouwelijke app-instellingen (PIN, authenticatievlaggen). Voor het opslaan van biometrische gegevens of grote documenten is EncryptedSharedPreferences niet geschikt — gebruik EncryptedFile of Room met SQLCipher.
Algemene regel: als gegevenslek de gebruiker of het bedrijf schaadt — gebruik EncryptedSharedPreferences. Als gegevens alleen cosmetisch zijn (thema, taal, sortering) — gewone SharedPreferences. EncryptedSharedPreferences heeft zin om meteen te implementeren, zonder refactoring: vervanging in een bestaand project vereist migratie en verwerking van oude onversleutelde gegevens.
Onthoud dat EncryptedSharedPreferences gegevens alleen op schijf beschermt — niet tijdens het uitvoeren van de app. Als een aanvaller toegang heeft tot het procesgeheugen, kunnen ontsleutelde gegevens worden onderschept. Gebruik extra bescherming: ProGuard/DexGuard voor code-obfuscaties/
Veelgestelde vragen
Jetpack DataStore — is een moderner alternatief voor SharedPreferences, gebaseerd op Flow en Kotlin-coroutines. DataStore versleutelt gegevens niet standaard, maar kan worden gecombineerd met EncryptedSharedPreferences of worden gebruikt met handmatige versleuteling via Proto DataStore met cryptografische protocollen.
Niet aanbevolen. EncryptedSharedPreferences is bedoeld voor kleine hoeveelheden (tot 100-200 KB). Gebruik voor grote gegevens Room met SQLCipher of bestandsversleuteling via EncryptedFile uit dezelfde AndroidX Security-bibliotheek.
Nee, automatische schemamigratie bestaat niet. Bij wijziging van de gegevensstructuur moet de ontwikkelaar handmatig oude gegevens lezen via oude KeyGen en schrijven via nieuwe. Het wordt aanbevolen de schemaversie in een aparte parameter op te slaan.
AndroidX Security 1.0.0 ondersteunt API 19+ (Android KitKat). Versie 1.1.0-alpha06 ondersteunt ook API 19+. Voor StrongBox is API 28+ en een apparaat met hardwarematige ondersteuning vereist (Google Pixel 3+, Samsung Galaxy S9+).
Ja, refresh token — is een van de belangrijkste gebruiksscenario's. AES-256 GCM-versleuteling, hoofdsleutel in Keystore, biometrische beveiliging — voldoende niveau voor OAuth-tokens. Voor access token met korte levensduur is het ook geschikt, hoewel sommige teams er de voorkeur aan geven het in het geheugen op te slaan.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook