Android Keystore — egy Android rendszermechanizmus kriptográfiai kulcsok biztonságos tárolására hardveres izolációban. A rendszer Trusted Execution Environment (TEE)-t használ ARM TrustZone-eszközökön vagy dedikált Secure Element-et a kulcsok chip szintű védelmére. A Android Open Source Project szerint a Keystore támogatja az RSA, EC, AES és HMAC algoritmusokat kulcsok közvetlenül a védett környezetben történő generálásával.
Főbb pontok
Android Keystore — egy kriptográfiai szolgáltató (provider), amely az Androidban API 1-től (Android 1.0) kezdve van implementálva, de a teljes hardveres támogatás az Android 4.3-mal (API 18) jelent meg. A Keystore megoldja a privát kulcsok biztonságos tárolásának problémáját úgymódon, hogy még az operációs rendszer kompromittálása esetén sem tudja a támadó kivonni a kulcsokat nyílt formában.
Az Android Keystore architektúrája három rétegből áll: alkalmazási API (java.security.KeyStore), rendszerszolgáltatás (keystore daemon) és hardveres réteg (Keymaster HAL). Az alkalmazás a szabványos Java Cryptography Architecture (JCA) API-n keresztül fér hozzá, és a rendszerszolgáltatás a TEE-ben működő Keymasterhez irányítja a kéréseket.
Minden kriptográfiai művelet kulcsokkal (aláírás, visszafejtés) a TEE vagy Secure Element belsejében történik. A kulcsok soha nem hagyják el a védett környezetet — az alkalmazás csak egy aliast kap a kulcsra hivatkozvá. Ez alapvető különbség a szoftveres KeyStore-okhoz képest, ahol a kulcsok potenciálisan elérhetők a folyamat memóriájában.
A szabványos JKS (Java KeyStore) vagy BKS (Bouncy Castle) a kulcsokat jelszóval védett fájlokban tárolja. Az Android Keystore hardveres izolációban tárolja a kulcsokat, ahol még a root felhasználótól is védve vannak. A JKS sebezhető a fájlrendszer közvetlen elérésével szemben, az Android Keystore — nem.
Másik különbség: az Android Keystore-ban a kulcsok szigorú használati paraméterekkel rendelkeznek (purpose — csak sign/verify/encrypt/decrypt), amelyek a generáláskor kerülnek beállításra. Ezek később nem változtathatók meg, ami megakadályozza a kulcs helytelen használatát.
Új kulcs létrehozásakor az alkalmazás meghívja a KeyPairGenerator-t vagy KeyGenerator-t KeyGenParameterSpec-szel, amely tartalmazza a jövőbeli kulcs összes paraméterét. A rendszer továbbítja a kérést a Keymaster HAL-nak, amely a TEE belsejében generálja a kulcsot és visszaad egy aliast.
A KeyGenParameterSpec.Builder metódus kötelező paramétereket fogad el: kulcs név a Keystore-ban, cél (PURPOSE_SIGN, PURPOSE_ENCRYPT), algoritmus (RSA, EC, AES). További: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometria), keyValidityStart/End (időbeli korlátozások).
A paraméterek beállítása után a KeyPairGenerator.generateKeyPair() visszaad egy KeyPair-t, ahol a PrivateKey egy objektum, amely a műveleteket a Keymaster-re delegálja. A nyilvános kulcs kivonható, a privát — nem. Csak a TEE belsejében létezik.
import java.security.KeyPairGenerator
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
fun generateKey(alias: String) {
val spec = KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
).setDigests(KeyProperties.DIGEST_SHA256)
.setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
.setUserAuthenticationRequired(true)
.build()
val kpGen = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
"AndroidKeyStore"
)
kpGen.initialize(spec)
kpGen.generateKeyPair()
}
A Signature ECDSA vagy RSA-PSS számára a szabványos API-n keresztül jön létre: Signature.getInstance(algorithm).initSign(privateKey). Az aláírási művelet a TEE-ben történik: az alkalmazás elküldi az adatokat, a Keymaster hardveresen aláírja őket és visszaadja az aláírást. A kulcs és az adatok nem keverednek a megosztott memóriában.
A biometrikus védelemhez az aláírás előtt hitelesíteni kell a felhasználót BiometricPrompt-on keresztül. Sikeres hitelesítés nélkül a Keymaster nem végzi el a műveletet, CryptoAuthenticationException-t dobva.
import java.security.KeyStore
import java.security.Signature
import androidx.biometric.BiometricPrompt
fun signWithBiometric(alias: String) {
val ks = KeyStore.getInstance("AndroidKeyStore")
ks.load(null)
val entry = ks.getEntry(alias, null) as KeyStore.PrivateKeyEntry
val signature = Signature.getInstance("SHA256withRSA")
signature.initSign(entry.privateKey)
// BiometricPrompt CryptoObject(signature) kéréssel FaceID/PIN-t kér
}
Az Android két kulcstárolási módot támogat: szoftveres (TEE nélküli eszközökön) és hardveres (TEE-vel vagy Secure Element-tel rendelkező eszközökön). A mód az SoC képességeitől és az Android verziójától függ.
A Trusted Execution Environment nélküli eszközökön (Android 4.3 előtt vagy olcsó SoC) a kulcsok titkosított formában tárolódnak egy, a zárolási képernyő jelszavából származó főkulcs segítségével. Ez a mód kevésbé biztonságos — a kulcsok elérhetők a folyamat memóriájában a kriptográfiai műveletek során.
A védelmi szint a KeyStore fájljának AES-256-GCM-mel történő titkosításán alapul. A titkosítási kulcs a felhasználó jelszava vagy PIN-kódja alapján generálódik Scrypt-en keresztül (PBKDF2 nagyszámú iterációval).
A modern eszközökön Keymaster 4.x használatos a TEE-ben (ARM TrustZone). A kulcsok kizárólag a TrustZone-on belül generálódnak, tárolódnak és használódnak. Még a Linux kernel sem fér hozzá a privát kulcsokhoz — csak a Keymaster HAL végezhet műveleteket.
Secure Element (például eSE a Samsung Knox-ban vagy StrongBox a Google Pixel 3+-ban) — egy különálló chip saját processzorral és memóriával. Common Criteria EAL 4+ tanúsítvánnyal rendelkezik és maximális védelmi szintet nyújt, beleértve a fizikai felnyitás elleni védelmet.
| Típus | Tárolási hely | Védelmi szint | Elérhető API-tól |
|---|---|---|---|
| Software | Fájl /data/misc/keystore | Közepes (AES-256) | API 1+ |
| Keymaster 3 | TEE (TrustZone) | Magas | API 23+ |
| Keymaster 4 | TEE + Secure I/O | Nagyon magas | API 28+ |
| StrongBox | Hardveres Secure Element | Maximális | API 28+, opcionális |
Az Android Keystore integrálva van a Java Cryptography Architecture (JCA)-ba. A szolgáltató eléréséhez a szabványos KeyStore.getInstance("AndroidKeyStore") használatos. Az API API 18-tól érhető el.
A KeyStore.load(null) metódus betölti az aktuális alkalmazás KeyStore konténerét. Jelszó nem szükséges — az Android az alkalmazás kontextusát és annak UID-jét használja a hozzáférés elkülönítésére. Minden alkalmazás csak a saját bejegyzéseit látja, kivéve ha megosztott UID-t használnak.
A setEntry és getEntry metódusok KeyStore.PrivateKeyEntry, SecretKeyEntry vagy TrustedCertificateEntry típusokkal dolgoznak. A ProtectionParameter paraméter mindig null az Android Keystore számára (a védelem rendszerszinten van implementálva).
import java.security.KeyStore
import java.security.cert.Certificate
import android.security.keystore.KeyProtection
fun storeSecretKey(alias: String, key: SecretKey) {
val ks = KeyStore.getInstance("AndroidKeyStore")
ks.load(null)
val prot = KeyProtection.Builder(
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.build()
ks.setEntry(alias, KeyStore.SecretKeyEntry(key), prot)
}
A KeyCharacteristics segítségével meghatározható, hogy a kulcs melyik környezetben van tárolva: szoftveres KeyStore, TEE vagy StrongBox. A getKeyCharacteristics() metódus flag-ek halmazát adja vissza: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometria).
Az Android Keystore a kriptográfiai algoritmusok széles választékát támogatja, három kategóriára osztva: aszimmetrikus, szimmetrikus és MAC. Az egyes algoritmusok támogatása a Keymaster HAL verziójától függ.
RSA (1024–4096 bit) — aláíráshoz (PKCS1, PSS) és titkosításhoz (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — ECDSA aláíráshoz és ECDH kulcscseréhez. AES (128, 256 bit) — szimmetrikus titkosításhoz CBC, CTR, GCM módokban. HMAC (SHA1, SHA256, SHA512) — üzenet-hitelesítéshez.
Minden kulcshoz beállításra kerül a setPurposes, amely korlátozza a lehetséges műveleteket. Egy PURPOSE_SIGN-tel rendelkező RSA kulcs nem használható titkosításra, még akkor sem, ha a támadó hozzáfér az API-hoz. Ez a kulcshasználat kikényszerítése hardveres szinten.
A Keymaster tartalmaz egy számlálót a sikertelen biometrikus hitelesítési kísérletekről. Adott számú sikertelen kísérlet után (a setInvalidatedByBiometricEnrollment segítségével konfigurálható) a kulcs elérhetetlenné válik és törlést/újragenerálást igényel. Az összes biometrikus sablon törlésekor az összes userAuthenticationRequired=true kulcs automatikusan érvénytelenítődik.
Emellett támogatott a Key Attestation (Android 8.1+): az alkalmazás kérésére a Keymaster aláír egy tanúsítványt a kulcs jellemzőiről (hardveres/szoftveres, algoritmus, purges). A szerver ellenőrizheti ezt a tanúsítványt annak megerősítésére, hogy a kulcs megbízható környezetben készült.
Gyakran Ismételt Kérdések
Java KeyStore a kulcsokat jelszóval védett fájlban (JKS, BKS) tárolja. Az Android Keystore a TEE vagy Secure Element hardveres izolációját használja. A Java KeyStore sebezhető root hozzáféréssel szemben, az Android Keystore — nem, mert a privát kulcsok soha nem hagyják el a védett környezetet.
Igen, a KeyStore.setEntry segítségével KeyProtection-nel. Az importált kulcsnak azonban nem lesz hardveres védelme — a szoftveres Keystore-ban tárolódik, a főkulccsal titkosítva. A maximális biztonság érdekében mindig a Keystore-on belül generálja a kulcsokat.
Használja a KeyChain.isBoundKeyAlgorithm-t vagy ellenőrizze a KeyCharacteristics-t a kulcs generálása után. A FLAG_HARDWARE jelenléte a jellemzőkben azt jelenti, hogy a kulcs TEE-ben készült. Ellenőrizheti az android.security.keystore.isHardwareBacked() függvényt is.
Az alkalmazás eltávolításakor az Android eltávolítja összes kulcsát a Keystore-ból. Az adatok visszavonhatatlanul elvesznek. Újratelepítéskor az alkalmazásnak új kulcsokat kell generálnia. A kulcsok TEE-n keresztüli biztonsági mentése architekturális okokból lehetetlen.
Zárolt eszközön a Keymaster nem végez semmilyen műveletet. A userAuthenticationRequired=true kulcsok minden alkalommal biometrikus megerősítést igényelnek. Még root hozzáféréssel sem tudja a támadó közvetlenül meghívni a Keymaster-t — csak az Android Keystore szolgáltatáson keresztül.
Összefoglaló
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