KeyStore (Android) — je implementace kryptografického poskytovatele Java Cryptography Architecture (JCA) integrovaná do Androidu pro bezpečné ukládání klíčů s možností hardwarové izolace. Od Androidu 4.3 (API 18) KeyStore podporuje hardwarové klíče prostřednictvím Keymaster HAL, a od Androidu 9 (API 28) — StrongBox Keymaster pro klíče ve vyhrazeném Secure Element. Podle Android Security Documentation nahrazuje poskytovatel „AndroidKeyStore” standardní Bouncy Castle nebo OpenSSL KeyStore a poskytuje systémovou ochranu proti neoprávněnému extrahování klíčů.
Hlavní body
KeyStore v Androidu — není samostatná aplikace nebo soubor, ale kryptografický poskytovatel implementující rozhraní java.security.KeyStore. Poskytuje jednotné API pro ukládání a používání soukromých klíčů, symetrických klíčů a certifikátů důvěryhodných autorit (CA). Poskytovatel je registrován pod názvem „AndroidKeyStore” a je přístupný prostřednictvím standardního KeyStore.getInstance().
Před Androidem 4.3 byly kryptografické operace prováděny softwarově prostřednictvím Bouncy Castle. S Androidem 4.3 se objevil Keymaster HAL 1.0, který umožnil použití TEE na ARM TrustZone. Android 6.0 (API 23) přidal Keymaster 2.0 s podporou hardwarové autentizace otiskem prstu. Android 9 (API 28) představil Keymaster 4.0 a StrongBox Keymaster pro vyhrazený Secure Element.
Každá verze Keymaster přidává nové možnosti a zlepšuje izolaci klíčů. Moderní zařízení (2022+) musí podporovat Keymaster 4.0 pro certifikaci Google Mobile Services, což zaručuje přítomnost TEE pro všechny Android aplikace.
Android KeyStore se skládá ze tří úrovní: Java API (KeyStore, KeyPairGenerator), systémový proces keystore (C++, funguje jako system service) a Keymaster HAL (knihovna v TEE nebo Secure Element). Aplikace volá API, služba keystore směruje požadavek do Keymaster a operace se provádí v chráněném prostředí.
Všechny soukromé klíče jsou uloženy v TEE a nelze je číst z uživatelského prostoru. Dokonce ani systémová služba keystore nemá přístup k holým klíčům — pouze k handle, které ukazují na klíče uvnitř Keymaster.
Android KeyStore implementuje standardní rozhraní poskytovatele služeb JCA. Když aplikace zavolá Cipher.getInstance(„RSA/ECB/PKCS1Padding”, „AndroidKeyStore”), Android Security Provider deleguje operaci do Keymaster prostřednictvím řetězce: Java → JNI → keystore service → Keymaster HAL.
Poskytovatel AndroidKeyStore se registruje automaticky při spuštění procesu. Jeho priorita je vyšší než u Bouncy Castle nebo Conscrypt. Proto při volání KeyStore.getInstance() bez zadání poskytovatele je ve většině případů vrácen AndroidKeyStore. Pro explicitní volání použijte KeyStore.getInstance(„AndroidKeyStore”).
Každá Android aplikace má izolovaný kontejner v KeyStore. Aplikace se stejným UID (shared userId) mohou mít sdílený přístup k určitým klíčům, ale standardní konfigurace zaručuje, že aplikace A nemůže číst klíče aplikace B.
load(null) — inicializace KeyStore. Parametr je pro AndroidKeyStore vždy null. setEntry — uložení klíče s uvedením KeyProtection (purposes, digest, padding). getEntry — získání KeyStore.PrivateKeyEntry, SecretKeyEntry nebo TrustedCertificateEntry. containsAlias — kontrola existence klíče. deleteEntry — odstranění klíče (nevratné).
import java.security.KeyStore
import java.security.KeyPairGenerator
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
object KeyStoreManager {
private val keyStore by lazy {
KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
}
fun createRsaKey(alias: String) {
val spec = KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
).setKeySize(2048)
.setDigests(KeyProperties.DIGEST_SHA256)
.setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
.build()
val kpg = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
"AndroidKeyStore"
)
kpg.initialize(spec)
kpg.generateKeyPair()
}
}
Android KeyStore podporuje širokou škálu kryptografických algoritmů, která se liší v závislosti na verzi Keymaster HAL na zařízení. Vývojář může získat seznam podporovaných algoritmů prostřednictvím KeyGenParameterSpec.Builder při pokusu o generování — nekompatibilní parametry způsobují InvalidAlgorithmParameterException.
RSA (1024–4096 bitů) — pro podpis (PKCS1, PSS s SHA-1/SHA-256/SHA-384/SHA-512) a šifrování (OAEP s SHA-1/SHA-256). EC (P-224, P-256, P-384, P-521) — pro podpis ECDSA a dohodu o klíči ECDH. X25519 a Ed25519 — od Androidu 12 (API 31) pro moderní kryptografické protokoly.
Pro asymetrické klíče Vždy generujte uvnitř Keymaster, NIKDY neimportujte soukromé klíče. Importované soukromé klíče nejsou hardwarově chráněny — jsou uloženy v softwarové vrstvě a jsou zranitelné při kompromitaci AP.
AES (128, 256 bitů) — pro symetrické šifrování v režimech CBC, CTR, GCM. HMAC (SHA-1, SHA-256, SHA-512) — pro autentizaci zpráv. ChaCha20 (Android 12+) — pro vysoce výkonné proudové šifrování s autentizací Poly1305.
| Algoritmus | Keymaster | Účel | API |
|---|---|---|---|
| RSA | KM 1.0+ | Podpis, šifrování | 18+ |
| EC | KM 1.0+ | ECDSA, ECDH | 18+ |
| AES | KM 2.0+ | Symetrické šifrování | 23+ |
| HMAC | KM 2.0+ | Autentizační kód | 23+ |
| ChaCha20 | KM 3.0+ | Proudové šifrování | 31+ |
| X25519/E25519 | KM 3.0+ | Výměna klíčů | 31+ |
KeyStore.PrivateKeyEntry — obsahuje soukromý klíč (neexportovatelný) a řetězec certifikátů. KeyStore.SecretKeyEntry — pro symetrické klíče. KeyStore.TrustedCertificateEntry — pro důvěryhodné CA certifikáty. Veřejné klíče jsou k dispozici pro export pomocí keyStore.getCertificate(alias).publicKey.
Podívejme se na plný scénář: generování AES klíče pro šifrování dat a generování EC klíče pro podpis s biometrickou ochranou. Oba klíče jsou vytvořeny uvnitř Android KeyStore s hardwarovou podporou.
AES klíč se vytváří pomocí KeyGenerator s KeyGenParameterSpec. Parametry: PURPOSE_ENCRYPT + PURPOSE_DECRYPT, BLOCK_MODE_GCM (doporučený režim s autentizací), ENCRYPTION_PADDING_NONE (pro GCM padding není třeba).
import javax.crypto.KeyGenerator
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
fun generateAndEncrypt(alias: String, plainText: ByteArray): ByteArray {
val spec = KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
.build()
val kg = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
kg.initialize(spec)
kg.generateKey()
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, getKeyFromStore(alias))
return cipher.doFinal(plainText)
}
EC klíč s userAuthenticationRequired=true vyžaduje autentizaci uživatele před každou operací podpisu. K tomu se používá BiometricPrompt s CryptoObject obsahujícím objekt Signature. Po úspěšné biometrii Keymaster povolí operaci.
fun createBiometricSignKey(alias: String) {
val spec = KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_SIGN
).setAlgorithmParameterSpec(
ECGenParameterSpec("secp256r1")
).setDigests(KeyProperties.DIGEST_SHA256)
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
.build()
val kpg = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_EC,
"AndroidKeyStore"
)
kpg.initialize(spec)
kpg.generateKeyPair()
}
Android KeyStore poskytuje hardwarové záruky bezpečnosti, které softwarové KeyStore (JKS, BKS) nemohou poskytnout. Klíče jsou chráněny na úrovni SoC a ani úplná kontrola nad uživatelským prostorem Androidu neumožňuje extrakci soukromého klíče.
Key Attestation — mechanismus, který umožňuje aplikaci (a serveru) ověřit, v jakém prostředí byl klíč vytvořen. Android Keystore podepisuje certifikát obsahující seznam charakteristik klíče: algoritmus, velikost, purges, hardware-backed (True/False), origin (GENERATED, IMPORTED). Server ověřuje řetězec certifikátů až ke kořenovému certifikátu Google.
To je kritické pro finanční aplikace: server může vyžadovat, aby byl klíč vytvořen v hardwarovém prostředí (Hardware-Backed = True), a odmítat klíče vytvořené v softwarovém Keystore. Key Attestation zabraňuje útokům, při kterých útočník nahrazuje Keystore emulátorem.
setInvalidatedByBiometricEnrollment(true) znamená, že klíč bude automaticky odstraněn Keymasterem při změně nebo odstranění biometrických šablon uživatele. To je ochrana proti útokům, při kterých útočník přidá svůj otisk prstu k existujícímu účtu. Po přidání nového otisku se staré klíče stanou nedostupné.
Počítadlo neúspěšných pokusů o biometrickou autentizaci je také spravováno Keymasterem. Po maxBiometricAttempt (nastavuje výrobce, obvykle 5) Keymaster zablokuje všechny operace s biometrickými klíči na 30 sekund. Po 10 neúspěšných pokusech — až do zadání hesla zařízení (tajného PINu).
Často kladené otázky
Bouncy Castle (BKS) — softwarový KeyStore, který ukládá klíče v souboru chráněném heslem. Android KeyStore používá hardwarovou izolaci TEE/StrongBox. Klíče BKS lze extrahovat s root přístupem, klíče Android KeyStore nikoli. BKS je vhodný pro CA certifikáty, Android KeyStore pro soukromé klíče.
Ano, pokud je při generování uvedeno PURPOSE_ENCRYPT or PURPOSE_DECRYPT or PURPOSE_SIGN or PURPOSE_VERIFY. Nejlepší praxí je však vytvářet samostatné klíče pro různé operace. To omezuje škody při kompromitaci jednoho z klíčů a je v souladu s principem nejmenších oprávnění.
Použijte KeyStore.getKeyCharacteristics(alias), dostupný přes android.security.keystore. Metoda vrací sadu příznaků: FLAG_HARDWARE — klíč v TEE, FLAG_SECURE_ELEMENT — klíč v StrongBox. Pokud nejsou příznaky žádné — klíč je softwarový.
Všechny klíče vytvořené s setInvalidatedByBiometricEnrollment(true) budou automaticky invalidovány Keymasterem. Při pokusu o použití aplikace obdrží KeyPermanentlyInvalidatedException. Data zašifrovaná těmito klíči budou nenávratně ztracena.
Hardwarové klíče (v TEE/StrongBox) nepodporují zálohování — jsou vázány na konkrétní zařízení. Softwarové klíče mohou být zahrnuty do zálohy Google Drive. Pro přenos dat mezi zařízeními šifrujte data na serveru a dešifrujte na novém zařízení.
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é