EncryptedSharedPreferences — är en komponent i AndroidX Security-biblioteket som ger transparent kryptering av data som sparas via SharedPreferences API. Till skillnad från vanliga SharedPreferences, där data lagras i en öppen XML-fil, krypterar EncryptedSharedPreferences automatiskt nycklar och värden innan de skrivs till disk. Enligt Android Developers använder biblioteket AES-256 GCM för värden och AES-256 SIV (RFC 5297) för nycklar, vilket säkerställer konfidentialitet och integritet för data.
Huvudpunkter
EncryptedSharedPreferences — är en klass från paketet androidx.security.crypto, introducerad i AndroidX Security 1.0.0 (2019). Den implementerar SharedPreferences-gränssnittet, men alla skrivoperationer (putString, putInt, putBoolean etc.) krypterar data i förväg, och läsoperationer dekrypterar dem innan de returneras.
Standard SharedPreferences sparar data i en XML-fil i applikationskatalogen (/data/data/package/shared_prefs/). Filen är inte krypterad — med root-åtkomst till enheten eller vid säkerhetskopieringsanalys läses all data som vanlig XML. Autentiseringstokens, API-nycklar, användarens personuppgifter blir tillgängliga för en angripare.
EncryptedSharedPreferences löser detta problem på biblioteksnivå: data krypteras innan de skrivs till disk och dekrypteras vid läsning. Utvecklaren behöver inte anropa kryptografiska funktioner manuellt — API:et förblir identiskt med vanliga SharedPreferences.
AndroidX Security biblioteket v1.0.0 släpptes i december 2019. EncryptedSharedPreferences ersatte den föråldrade metoden med manuell kryptering via Cipher + SharedPreferences. Den nuvarande stabila versionen är 1.1.0-alpha06 (2024), som stöder API 19+. Biblioteket är en del av Jetpack och kräver inga ytterligare behörigheter.
Enligt Google Security Blog (2024) är EncryptedSharedPreferences den rekommenderade metoden för att lagra konfidentiella applikationsinställningar som inte kräver synkronisering via molnet. För mer komplexa scenarier rekommenderas Room med kryptering via SQLCipher.
EncryptedSharedPreferences använder ett två-nivåers krypteringsschema: huvudnyckeln (Master Key) lagras i Android Keystore, och för datakryptering används härledda nycklar. Detta är en kombination av Keystore-skydd och prestanda för symmetrisk kryptering.
För värden används AES-256 GCM (Galois/Counter Mode) — autentiserat krypteringsläge (AEAD), som säkerställer konfidentialitet och integritet för data. För nycklar (parameternamn) tillämpas AES-256 SIV (RFC 5297) — deterministisk kryptering, nödvändig för sökning efter nyckel utan att avslöja dess innehåll.
Varje fil EncryptedSharedPreferences innehåller krypterade nyckel-värdepar. Filstruktur: först en rubrik med metadata (version, nyckelidentifierare), sedan en lista med krypterade poster. Filen är inte giltig XML och kan inte läsas i textredigerare.
Klassen MasterKey ansvarar för att skapa och hantera den 256-bitars huvudnyckel som lagras i Android Keystore. MasterKey.Builder möjliggör konfiguration: lagringstyp (Keystore eller programvara), biometriskt skydd, nyckelns livslängd. Som standard genereras huvudnyckeln i Android Keystore med AES/GCM/NoPadding-algoritmen.
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 tar emot fem parametrar: kontext, filnamn, huvudnyckel, krypteringsschema för nycklar och krypteringsschema för värden. Valet av scheman påverkar prestanda och skyddsnivå.
AES256_SIV — deterministisk kryptering: identiska nycklar ger alltid identisk krypterad text. Detta är nödvändigt för sökning efter nyckel (SharedPreferences.getX(key)). Nackdel: en angripare kan avgöra vilka nycklar som används från upprepade chiffertexter. AES256_SIV2 — förbättrad version med extra randomisering.
För värden används AES256_GCM. GCM lägger till en 12-byte IV (initieringsvektor) och en 16-byte autentiseringstagg till varje värde. Detta säkerställer konfidentialitet (ingen kan läsa värdet) och autentisering (ingen kan ändra värdet utan upptäckt).
Metoden setUserAuthenticationRequired(true) i MasterKey.Builder kräver biometrisk bekräftelse innan huvudnyckeln hämtas från Keystore. Detta lägger till ett extra lager: även om appen körs på en olåst enhet kan en angripare inte läsa EncryptedSharedPreferences utan Face ID eller Touch ID.
Viktigt: med setUserAuthenticationRequired blir huvudnyckeln otillgänglig om användaren har ändrat eller tagit bort biometrin. KeyPermanentlyInvalidatedException måste hanteras och en ny huvudnyckel måste skapas med datamigrering.
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) {
// Biometrin har ändrats — nyckeln måste återskapas
}
}
Låt oss titta på ett komplett exempel på integration av EncryptedSharedPreferences i en Android-app i Kotlin. Biblioteket androidx.security:security-crypto läggs till via Gradle.
I filen build.gradle (app) lägg till: implementation “androidx.security:security-crypto:1.1.0-alpha06”. För Kotlin-projekt krävs även kotlin-stdlib. Initiering av MasterKey sker en gång, vanligtvis i Application.onCreate eller via en DI-behållare.
Efter att ha skapat en instans av EncryptedSharedPreferences skiljer sig API:et inte från vanliga SharedPreferences. edit() returnerar en Editor, alla metoder (putString, getString, putBoolean, getBoolean) fungerar på samma sätt. Skillnaden finns bara inuti: data krypteras vid skrivning och dekrypteras vid läsning.
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()
}
}
För migrering av befintlig data från oskyddade SharedPreferences till EncryptedSharedPreferences krävs: läs all data från den gamla filen, skapa en ny EncryptedSharedPreferences, skriv all data, ta bort den gamla filen. Google tillhandahåller ingen inbyggd migreringsfunktion — utvecklaren implementerar den själv.
Valet mellan SharedPreferences och EncryptedSharedPreferences beror på typen av lagrad data. För inställningar av gränssnittet (tema, språk, sortering) är vanliga SharedPreferences tillräckliga. För konfidentiell information (tokens, lösenord, nycklar) är EncryptedSharedPreferences obligatoriskt.
EncryptedSharedPreferences är långsammare än vanliga på grund av kryptografiska operationer. Att skriva ett strängvärde tar ~5-15 ms (beroende på datastorlek och hårdvaruacceleration av AES). Läsning — 2-5 ms. För de flesta applikationer är detta omärkligt, men vid batchoperationer (migrering, återställning) är det bättre att använda apply() istället för commit().
Vanliga SharedPreferences ger inget kryptografiskt skydd: XML-filen läses av vilken process som helst med root-åtkomst eller via adb backup. EncryptedSharedPreferences krypterar data på applikationsnivå och huvudnyckeln lagras i Android Keystore med möjlighet till hårdvaruskydd (StrongBox).
| Egenskap | SharedPreferences | EncryptedSharedPreferences |
|---|---|---|
| Lagring | Öppen XML | Krypterad binär fil |
| Kryptering | Nej | AES-256 GCM + SIV |
| Nyckelskydd | Nej | Android Keystore + StrongBox |
| Prestanda | 0.1-1 ms | 2-15 ms |
| Rekommendation | UI-inställningar | Tokens, nycklar, PII |
Använd EncryptedSharedPreferences för att lagra: OAuth refresh-token, API-nycklar för externa tjänster, användarens e-post eller telefonnummer, konfidentiella applikationsinställningar (PIN, autentiseringsflaggor). För lagring av biometrisk data eller stora dokument är EncryptedSharedPreferences inte lämpligt — använd EncryptedFile eller Room med SQLCipher.
Allmän regel: om dataläckage skadar användaren eller verksamheten — använd EncryptedSharedPreferences. Om data endast är kosmetiska (tema, språk, sortering) — vanliga SharedPreferences. EncryptedSharedPreferences är vettigt att implementera omedelbart, utan omfaktorering: ersättning i ett befintligt projekt kräver migrering och hantering av gamla okrypterade data.
Kom ihåg att EncryptedSharedPreferences endast skyddar data på disken — inte under applikationens körning. Om en angripare har åtkomst till processminnet kan dekrypterad data fångas upp. Använd extra skydd: ProGuard/DexGuard för kodobfuskering.
Vanliga frågor
Jetpack DataStore — är ett mer modernt alternativ till SharedPreferences, baserat på Flow och Kotlin-korutiner. DataStore krypterar inte data som standard, men kan kombineras med EncryptedSharedPreferences eller användas med manuell kryptering via Proto DataStore med kryptografiska protokoll.
Rekommenderas inte. EncryptedSharedPreferences är avsett för små mängder (upp till 100-200 KB). För stora data, använd Room med SQLCipher eller filkryptering via EncryptedFile från samma AndroidX Security-bibliotek.
Nej, automatisk schemamigrering finns inte. Vid ändring av datastrukturen måste utvecklaren manuellt läsa gammal data via gammal KeyGen och skriva den via ny. Det rekommenderas att lagra schemaversionen i en separat parameter.
AndroidX Security 1.0.0 stöder API 19+ (Android KitKat). Version 1.1.0-alpha06 stöder också API 19+. För StrongBox krävs API 28+ och en enhet med hårdvarustöd (Google Pixel 3+, Samsung Galaxy S9+).
Ja, refresh-token — är ett av de främsta användningsscenarierna. AES-256 GCM-kryptering, huvudnyckel i Keystore, biometriskt skydd — tillräcklig nivå för OAuth-tokens. För access-token med kort livslängd är det också lämpligt, även om vissa team föredrar att lagra den i minnet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också