EncryptedSharedPreferences — je komponenta knihovny AndroidX Security, která zajišťuje transparentní šifrování dat ukládaných prostřednictvím API SharedPreferences. Na rozdíl od běžných SharedPreferences, kde jsou data uložena v otevřeném XML souboru, EncryptedSharedPreferences automaticky šifruje klíče a hodnoty před zápisem na disk. Podle Android Developers knihovna používá AES-256 GCM pro hodnoty a AES-256 SIV (RFC 5297) pro klíče, čímž zajišťuje důvěrnost a integritu dat.
Hlavní body
EncryptedSharedPreferences — je třída z balíčku androidx.security.crypto, představená v AndroidX Security 1.0.0 (2019). Implementuje rozhraní SharedPreferences, ale všechny operace zápisu (putString, putInt, putBoolean atd.) data předem šifrují a operace čtení je před vrácením dešifrují.
Standardní SharedPreferences ukládají data do XML souboru v adresáři aplikace (/data/data/package/shared_prefs/). Soubor není zašifrován — při root přístupu k zařízení nebo při analýze zálohy jsou všechna data čitelná jako běžný XML. Autentizační tokeny, API klíče, osobní údaje uživatele se stávají dostupnými útočníkovi.
EncryptedSharedPreferences řeší tento problém na úrovni knihovny: data jsou šifrována před zápisem na disk a dešifrována při čtení. Vývojář nemusí ručně volat kryptografické funkce — API zůstává identické s běžnými SharedPreferences.
Knihovna AndroidX Security v1.0.0 byla vydána v prosinci 2019. EncryptedSharedPreferences nahradila zastaralý přístup s ručním šifrováním přes Cipher + SharedPreferences. Aktuální stabilní verze je 1.1.0-alpha06 (2024), podporující API 19+. Knihovna je součástí Jetpack a nevyžaduje další oprávnění.
Podle Google Security Blog (2024) je EncryptedSharedPreferences doporučeným způsobem ukládání důvěrných nastavení aplikace, která nevyžadují synchronizaci přes cloud. Pro složitější scénáře se doporučuje Room s šifrováním přes SQLCipher.
EncryptedSharedPreferences používá dvouúrovňové schéma šifrování: hlavní klíč (Master Key) je uložen v Android Keystore a pro šifrování dat se používají odvozené klíče. Jedná se o kombinaci ochrany Keystore a výkonu symetrického šifrování.
Pro hodnoty se používá AES-256 GCM (Galois/Counter Mode) — režim autentizovaného šifrování (AEAD), zajišťující důvěrnost a integritu dat. Pro klíče (názvy parametrů) se aplikuje AES-256 SIV (RFC 5297) — deterministické šifrování, nezbytné pro vyhledávání podle klíče bez prozrazení jeho obsahu.
Každý soubor EncryptedSharedPreferences obsahuje zašifrované páry klíč-hodnota. Struktura souboru: nejprve hlavička s metadaty (verze, identifikátor klíče), poté seznam zašifrovaných záznamů. Soubor není platný XML a není čitelný v textových editorech.
Třída MasterKey je zodpovědná za vytvoření a správu 256bitového hlavního klíče, který je uložen v Android Keystore. MasterKey.Builder umožňuje konfiguraci: typ úložiště (Keystore nebo softwarové), ochrana biometrií, životnost klíče. Ve výchozím nastavení je hlavní klíč generován v Android Keystore s algoritmem AES/GCM/NoPadding.
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 přijímá pět parametrů: kontext, název souboru, hlavní klíč, schéma šifrování klíčů a schéma šifrování hodnot. Volba schémat ovlivňuje výkon a úroveň ochrany.
AES256_SIV — deterministické šifrování: identické klíče vždy poskytují identický zašifrovaný text. To je nezbytné pro vyhledávání podle klíče (SharedPreferences.getX(key)). Nevýhoda: útočník může určit, které klíče se používají, podle opakujících se šifer. AES256_SIV2 — vylepšená verze s dodatečnou randomizací.
Pro hodnoty se používá AES256_GCM. GCM přidává 12bajtový IV (inicializační vektor) a 16bajtový autentizační tag ke každé hodnotě. To zajišťuje důvěrnost (nikdo nemůže hodnotu přečíst) a autentizaci (nikdo nemůže hodnotu změnit bez odhalení).
Metoda setUserAuthenticationRequired(true) v MasterKey.Builder vyžaduje biometrické potvrzení před získáním hlavního klíče z Keystore. To přidává další vrstvu: i když aplikace běží na odemčeném zařízení, útočník nemůže přečíst EncryptedSharedPreferences bez Face ID nebo Touch ID.
Důležité: při setUserAuthenticationRequired se hlavní klíč stane nedostupným, pokud uživatel změnil nebo smazal biometrii. Je nutné zpracovat KeyPermanentlyInvalidatedException a vytvořit nový hlavní klíč s migrací dat.
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 se změnila — je třeba znovu vytvořit klíč
}
}
Podívejme se na úplný příklad integrace EncryptedSharedPreferences v Android aplikaci v Kotlinu. Knihovna androidx.security:security-crypto se přidává přes Gradle.
Do souboru build.gradle (app) přidejte: implementation „androidx.security:security-crypto:1.1.0-alpha06“. Pro Kotlin projekty je také vyžadován kotlin-stdlib. Inicializace MasterKey probíhá jednorázově, obvykle v Application.onCreate nebo přes DI kontejner.
Po vytvoření instance EncryptedSharedPreferences se API neliší od běžných SharedPreferences. edit() vrací Editor, všechny metody (putString, getString, putBoolean, getBoolean) fungují analogicky. Rozdíl je pouze uvnitř: data jsou šifrována při zápisu a dešifrována při čtení.
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()
}
}
Pro migraci stávajících dat z nechráněných SharedPreferences do EncryptedSharedPreferences je nutné: přečíst všechna data ze starého souboru, vytvořit nový EncryptedSharedPreferences, zapsat všechna data, smazat starý soubor. Google neposkytuje vestavěný migrační nástroj — vývojář jej implementuje sám.
Výběr mezi SharedPreferences a EncryptedSharedPreferences závisí na typu ukládaných dat. Pro nastavení rozhraní (téma, jazyk, řazení) jsou běžné SharedPreferences dostatečné. Pro důvěrné informace (tokeny, hesla, klíče) je EncryptedSharedPreferences povinný.
EncryptedSharedPreferences je pomalejší než běžný kvůli kryptografickým operacím. Zápis jedné textové hodnoty trvá ~5-15 ms (závisí na velikosti dat a hardwarové akceleraci AES). Čtení — 2-5 ms. Pro většinu aplikací je to nepostřehnutelné, ale při dávkových operacích (migrace, obnova) se vyplatí použít apply() místo commit().
Běžné SharedPreferences neposkytují žádnou kryptografickou ochranu: XML soubor je čitelný jakýmkoli procesem s root přístupem nebo přes adb backup. EncryptedSharedPreferences šifruje data na úrovni aplikace a hlavní klíč je uložen v Android Keystore s možností hardwarové ochrany (StrongBox).
| Vlastnost | SharedPreferences | EncryptedSharedPreferences |
|---|---|---|
| Úložiště | Otevřený XML | Zašifrovaný binární soubor |
| Šifrování | Ne | AES-256 GCM + SIV |
| Ochrana klíčů | Ne | Android Keystore + StrongBox |
| Výkon | 0.1-1 ms | 2-15 ms |
| Doporučení | Nastavení UI | Tokeny, klíče, PII |
Použijte EncryptedSharedPreferences pro ukládání: OAuth refresh tokenu, API klíčů pro externí služby, emailu nebo telefonního čísla uživatele, důvěrných nastavení aplikace (PIN, autentizační příznaky). Pro ukládání biometrických dat nebo velkých dokumentů není EncryptedSharedPreferences vhodný — použijte EncryptedFile nebo Room s SQLCipher.
Obecné pravidlo: pokud únik dat poškodí uživatele nebo firmu — použijte EncryptedSharedPreferences. Pokud jsou data pouze kosmetická (téma, jazyk, řazení) — běžné SharedPreferences. EncryptedSharedPreferences má smysl implementovat ihned, bez refaktorování: nahrazení ve stávajícím projektu vyžaduje migraci a zpracování starých nešifrovaných dat.
Pamatujte, že EncryptedSharedPreferences chrání data pouze na disku — ne za běhu aplikace. Pokud má útočník přístup k paměti procesu, dešifrovaná data mohou být zachycena. Použijte dodatečnou ochranu: ProGuard/DexGuard pro obfuskaci kódu.
Často kladené otázky
Jetpack DataStore — je modernější alternativa k SharedPreferences, založená na Flow a Kotlin korutinách. DataStore ve výchozím nastavení nešifruje data, ale lze jej kombinovat s EncryptedSharedPreferences nebo používat s ručním šifrováním přes Proto DataStore s kryptografickými protokoly.
Nedoporučuje se. EncryptedSharedPreferences je určen pro malé objemy (do 100-200 KB). Pro velká data použijte Room s SQLCipher nebo šifrování souborů přes EncryptedFile ze stejné knihovny AndroidX Security.
Ne, automatická migrace schématu neexistuje. Při změně struktury dat musí vývojář ručně přečíst stará data přes starý KeyGen a zapsat je přes nový. Doporučuje se ukládat verzi schématu v samostatném parametru.
AndroidX Security 1.0.0 podporuje API 19+ (Android KitKat). Verze 1.1.0-alpha06 také podporuje API 19+. Pro StrongBox je vyžadováno API 28+ a zařízení s hardwarovou podporou (Google Pixel 3+, Samsung Galaxy S9+).
Ano, refresh token — je jeden z hlavních scénářů použití. Šifrování AES-256 GCM, hlavní klíč v Keystore, biometrická ochrana — dostatečná úroveň pro OAuth tokeny. Pro access token s krátkou životností je také vhodný, i když některé týmy preferují ukládání v paměti.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také