EncryptedSharedPreferences — az AndroidX Security könyvtár egyik összetevője, amely átlátható titkosítást biztosít a SharedPreferences API-n keresztül mentett adatok számára. Ellentétben a hagyományos SharedPreferences-szel, ahol az adatok nyílt XML-fájlban vannak tárolva, az EncryptedSharedPreferences automatikusan titkosítja a kulcsokat és értékeket a lemezre írás előtt. A Android Developers szerint a könyvtár AES-256 GCM-et használ az értékekhez és AES-256 SIV-t (RFC 5297) a kulcsokhoz, biztosítva az adatok bizalmasságát és integritását.
Főbb pontok
EncryptedSharedPreferences — egy osztály a androidx.security.crypto csomagból, amely az AndroidX Security 1.0.0-ban (2019) lett bevezetve. Implementálja a SharedPreferences interfészt, de minden írási művelet (putString, putInt, putBoolean stb.) előzetesen titkosítja az adatokat, az olvasási műveletek pedig visszafejtik azokat visszaadás előtt.
A szabványos SharedPreferences az adatokat XML-fájlban tárolja az alkalmazás könyvtárában (/data/data/package/shared_prefs/). A fájl nincs titkosítva — root hozzáféréssel az eszközhöz vagy a biztonsági mentés elemzésekor az összes adat olvasható egyszerű XML-ként. Az hitelesítési tokenek, API-kulcsok, a felhasználó személyes adatai hozzáférhetővé válnak a támadó számára.
EncryptedSharedPreferences könyvtár szintjén oldja meg ezt a problémát: az adatok titkosításra kerülnek a lemezre írás előtt, és visszafejtődnek olvasáskor. A fejlesztőnek nem kell manuálisan meghívnia kriptográfiai függvényeket — az API azonos marad a hagyományos SharedPreferences-szel.
Az AndroidX Security könyvtár v1.0.0 2019 decemberében jelent meg. Az EncryptedSharedPreferences felváltotta az elavult megközelítést, amely manuális titkosítást használt Cipher + SharedPreferences segítségével. A jelenlegi stabil verzió 1.1.0-alpha06 (2024), amely API 19+-t támogat. A könyvtár a Jetpack része, és nem igényel további engedélyeket.
A Google Security Blog (2024) szerint az EncryptedSharedPreferences az ajánlott módszer a bizalmas alkalmazásbeállítások tárolására, amelyek nem igényelnek felhőn keresztüli szinkronizálást. Összetettebb forgatókönyvekhez a Room titkosítással (SQLCipher) ajánlott.
EncryptedSharedPreferences kétszintű titkosítási sémát használ: a főkulcs (Master Key) az Android Keystore-ban van tárolva, és az adatok titkosításához származtatott kulcsokat használ. Ez a Keystore védelem és a szimmetrikus titkosítás teljesítményének kombinációja.
Az értékekhez AES-256 GCM (Galois/Counter Mode) használatos — hitelesített titkosítási mód (AEAD), amely biztosítja az adatok bizalmasságát és integritását. A kulcsokhoz (paraméternevek) AES-256 SIV (RFC 5297) alkalmazandó — determinisztikus titkosítás, amely szükséges a kulcs szerinti kereséshez anélkül, hogy felfedné a tartalmát.
Minden fájl EncryptedSharedPreferences titkosított kulcs-érték párokat tartalmaz. A fájl szerkezete: először egy fejléc metaadatokkal (verzió, kulcsazonosító), majd a titkosított bejegyzések listája. A fájl nem érvényes XML, és nem olvasható szövegszerkesztőkkel.
A MasterKey osztály felelős a 256 bites főkulcs létrehozásáért és kezeléséért, amely az Android Keystore-ban van tárolva. A MasterKey.Builder lehetővé teszi a konfigurációt: tárolás típusa (Keystore vagy szoftveres), biometrikus védelem, kulcs élettartama. Alapértelmezés szerint a főkulcs az Android Keystore-ban jön létre AES/GCM/NoPadding algoritmussal.
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 öt paramétert fogad: kontextus, fájlnév, főkulcs, kulcsok titkosítási sémája és értékek titkosítási sémája. A sémák kiválasztása befolyásolja a teljesítményt és a védelem szintjét.
AES256_SIV — determinisztikus titkosítás: azonos kulcsok mindig azonos titkosított szöveget adnak. Ez szükséges a kulcs szerinti kereséshez (SharedPreferences.getX(key)). Hátrány: a támadó megállapíthatja, hogy mely kulcsok használatosak az ismétlődő titkosított szövegekből. AES256_SIV2 — továbbfejlesztett verzió extra randomizációval.
Az értékekhez AES256_GCM használatos. A GCM 12 bájtos IV-t (inicializációs vektor) és 16 bájtos hitelesítési címkét ad minden értékhez. Ez biztosítja a bizalmasságot (senki sem olvashatja az értéket) és a hitelesítést (senki sem módosíthatja az értéket észlelés nélkül).
A setUserAuthenticationRequired(true) metódus a MasterKey.Builder-ben biometrikus megerősítést követel meg a főkulcs Keystore-ból való megszerzése előtt. Ez egy további réteget ad: még ha az alkalmazás egy feloldott eszközön fut is, a támadó nem olvashatja az EncryptedSharedPreferences-t Face ID vagy Touch ID nélkül.
Fontos: a setUserAuthenticationRequired esetén a főkulcs elérhetetlenné válik, ha a felhasználó megváltoztatta vagy törölte a biometrikus adatokat. Kezelni kell a KeyPermanentlyInvalidatedException kivételt, és új főkulcsot kell létrehozni adatmigrációval.
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) {
// A biometria megváltozott — a kulcsot újra kell létrehozni
}
}
Nézzünk egy teljes példát az EncryptedSharedPreferences integrációjára egy Android-alkalmazásban Kotlinban. Az androidx.security:security-crypto könyvtár Gradle-en keresztül adható hozzá.
A build.gradle (app) fájlba adja hozzá: implementation „androidx.security:security-crypto:1.1.0-alpha06“. Kotlin-projektekhez a kotlin-stdlib is szükséges. A MasterKey inicializálása egyszeri, általában az Application.onCreate-ban vagy DI-konténeren keresztül történik.
Az EncryptedSharedPreferences példány létrehozása után az API nem különbözik a hagyományos SharedPreferences-től. Az edit() egy Editor-t ad vissza, minden metódus (putString, getString, putBoolean, getBoolean) azonosan működik. A különbség csak belül van: az adatok titkosításra kerülnek íráskor és visszafejtődnek olvasáskor.
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()
}
}
A meglévő adatok migrációjához a védtelen SharedPreferences-ből az EncryptedSharedPreferences-be szükséges: olvassa ki az összes adatot a régi fájlból, hozzon létre egy új EncryptedSharedPreferences-t, írja ki az összes adatot, törölje a régi fájlt. A Google nem biztosít beépített migrátort — a fejlesztő maga implementálja.
A SharedPreferences és az EncryptedSharedPreferences közötti választás a tárolt adatok típusától függ. A felület beállításaihoz (téma, nyelv, rendezés) a hagyományos SharedPreferences elegendő. A bizalmas információkhoz (tokenek, jelszavak, kulcsok) az EncryptedSharedPreferences kötelező.
Az EncryptedSharedPreferences lassabb a hagyományosnál a kriptográfiai műveletek miatt. Egyetlen szöveges érték írása ~5-15 ms-ig tart (az adatok méretétől és az AES hardveres gyorsításától függően). Olvasás — 2-5 ms. A legtöbb alkalmazás számára ez észrevehetetlen, de kötegelt műveleteknél (migráció, helyreállítás) érdemes az apply()-t használni a commit() helyett.
A hagyományos SharedPreferences nem nyújt semmilyen kriptográfiai védelmet: az XML-fájlt bármely root hozzáféréssel rendelkező folyamat vagy adb backup segítségével olvashatja. Az EncryptedSharedPreferences alkalmazásszinten titkosítja az adatokat, a főkulcs pedig az Android Keystore-ban van tárolva hardveres védelem (StrongBox) lehetőségével.
| Jellemző | SharedPreferences | EncryptedSharedPreferences |
|---|---|---|
| Tárolás | Nyílt XML | Titkosított bináris fájl |
| Titkosítás | Nincs | AES-256 GCM + SIV |
| Kulcsvédelem | Nincs | Android Keystore + StrongBox |
| Teljesítmény | 0.1-1 ms | 2-15 ms |
| Ajánlás | UI beállítások | Tokenek, kulcsok, PII |
Használja az EncryptedSharedPreferences-t a következők tárolására: OAuth refresh token, API-kulcsok külső szolgáltatásokhoz, felhasználó e-mail címe vagy telefonszáma, bizalmas alkalmazásbeállítások (PIN, hitelesítési jelzők). Biometrikus adatok vagy nagy dokumentumok tárolására az EncryptedSharedPreferences nem alkalmas — használja az EncryptedFile-t vagy a Room-ot SQLCipher-rel.
Általános szabály: ha az adatszivárgás kárt okoz a felhasználónak vagy az üzletnek — használja az EncryptedSharedPreferences-t. Ha az adatok csak kozmetikaiak (téma, nyelv, rendezés) — hagyományos SharedPreferences. Az EncryptedSharedPreferences-t érdemes azonnal bevezetni, refaktorálás nélkül: a meglévő projektben történő csere migrációt és a régi titkosítatlan adatok feldolgozását igényel.
Ne feledje, hogy az EncryptedSharedPreferences csak a lemezen védi az adatokat — nem az alkalmazás futása közben. Ha a támadó hozzáfér a folyamat memóriájához, a visszafejtett adatok elfoghatók. Használjon további védelmet: ProGuard/DexGuard a kód obfuszkálásához.
Gyakran Ismételt Kérdések
Jetpack DataStore — egy modernebb alternatíva a SharedPreferences számára, Flow és Kotlin korutinokra épülve. A DataStore alapértelmezés szerint nem titkosítja az adatokat, de kombinálható az EncryptedSharedPreferences-szel, vagy használható manuális titkosítással a Proto DataStore-on keresztül kriptográfiai protokollokkal.
Nem ajánlott. Az EncryptedSharedPreferences kis mennyiségekhez (100-200 KB-ig) készült. Nagy adatokhoz használja a Room-ot SQLCipher-rel vagy fájltitkosítást az EncryptedFile-on keresztül ugyanabból az AndroidX Security könyvtárból.
Nem, automatikus séma-migráció nem létezik. Az adatstruktúra megváltoztatásakor a fejlesztőnek manuálisan kell kiolvasnia a régi adatokat a régi KeyGen-en keresztül, és kiírnia az újon keresztül. Ajánlott a séma verzióját külön paraméterben tárolni.
AndroidX Security 1.0.0 API 19+-t (Android KitKat) támogat. Az 1.1.0-alpha06 verzió szintén API 19+-t támogat. A StrongBox-hoz API 28+ és hardveres támogatással rendelkező eszköz szükséges (Google Pixel 3+, Samsung Galaxy S9+).
Igen, a refresh token — az egyik fő használati eset. AES-256 GCM titkosítás, főkulcs a Keystore-ban, biometrikus védelem — elegendő szint az OAuth tokenekhez. A rövid élettartamú access tokenhez is alkalmas, bár egyes csapatok inkább memóriában tárolják.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is