Android Keystore — je systémový mechanismus Androidu pro bezpečné ukládání kryptografických klíčů v hardwarové izolaci. Systém využívá Trusted Execution Environment (TEE) na zařízeních s ARM TrustZone nebo vyhrazený Secure Element k ochraně klíčů na úrovni čipu. Podle Android Open Source Project Keystore podporuje algoritmy RSA, EC, AES a HMAC s generováním klíčů přímo v zabezpečeném prostředí.
Hlavní
Android Keystore — je kryptografický poskytovatel (provider) implementovaný v Androidu od API 1 (Android 1.0), ale plná hardwarová podpora se objevila s Androidem 4.3 (API 18). Keystore řeší problém bezpečného ukládání soukromých klíčů tak, že i při kompromitaci operačního systému útočník nemůže extrahovat klíče v otevřené podobě.
Architektura Android Keystore se skládá ze tří vrstev: aplikační API (java.security.KeyStore), systémová služba (keystore daemon) a hardwarová vrstva (Keymaster HAL). Aplikace přistupuje prostřednictvím standardního API Java Cryptography Architecture (JCA) a systémová služba směruje požadavky na Keymaster pracující v TEE.
Všechny kryptografické operace s klíči (podpis, dešifrování) se provádějí uvnitř TEE nebo Secure Element. Klíče nikdy neopouštějí zabezpečené prostředí — aplikace obdrží pouze alias pro odkaz na klíč. To je zásadní rozdíl oproti softwarovým KeyStore, kde jsou klíče potenciálně přístupné v paměti procesu.
Standardní JKS (Java KeyStore) nebo BKS (Bouncy Castle) ukládá klíče v souborech chráněných heslem. Android Keystore ukládá klíče v hardwarové izolaci, kde jsou chráněny i před root uživatelem. JKS je zranitelný při přímém přístupu k souborovému systému, Android Keystore — nikoli.
Další rozdíl: v Android Keystore mají klíče přísné parametry použití (purpose — pouze sign/verify/encrypt/decrypt) nastavené při generování. Nelze je později změnit, což zabraňuje zneužití klíče.
Při vytváření nového klíče aplikace volá KeyPairGenerator nebo KeyGenerator s KeyGenParameterSpec, který obsahuje všechny parametry budoucího klíče. Systém předá požadavek Keymaster HAL, který generuje klíč uvnitř TEE a vrací alias.
Metoda KeyGenParameterSpec.Builder přijímá povinné parametry: název klíče v Keystore, účel (PURPOSE_SIGN, PURPOSE_ENCRYPT), algoritmus (RSA, EC, AES). Doplňkově: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometrie), keyValidityStart/End (časová omezení).
Po nastavení parametrů KeyPairGenerator.generateKeyPair() vrací KeyPair, kde PrivateKey je objekt delegující operace na Keymaster. Veřejný klíč lze extrahovat, soukromý — nikoli. Existuje pouze uvnitř TEE.
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()
}
Signature pro ECDSA nebo RSA-PSS se vytváří prostřednictvím standardního API: Signature.getInstance(algorithm).initSign(privateKey). Operace podpisu se provádí v TEE: aplikace odešle data, Keymaster je hardwarově podepíše a vrátí podpis. Klíč a data se nemísí ve sdílené paměti.
Pro biometrickou ochranu je nutné před podpisem autentizovat uživatele prostřednictvím BiometricPrompt. Bez úspěšné autentizace Keymaster operaci neprovede a vrátí CryptoAuthenticationException.
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 s CryptoObject(signature) žádá o FaceID/PIN
}
Android podporuje dva režimy ukládání klíčů: softwarový (na zařízeních bez TEE) a hardwarový (na zařízeních s TEE nebo Secure Element). Režim závisí na možnostech SoC a verzi Androidu.
Na zařízeních bez Trusted Execution Environment (před Androidem 4.3 nebo levné SoC) jsou klíče uloženy v šifrované podobě pomocí hlavního klíče odvozeného z hesla zamykací obrazovky. Tento režim je méně bezpečný — klíče jsou během kryptografických operací přístupné v paměti procesu.
Úroveň ochrany je založena na šifrování souboru KeyStore pomocí AES-256-GCM. Šifrovací klíč je generován na základě uživatelského hesla nebo PINu prostřednictvím Scrypt (PBKDF2 s velkým počtem iterací).
Na moderních zařízeních se používá Keymaster 4.x v TEE (ARM TrustZone). Klíče jsou generovány, ukládány a používány výhradně uvnitř TrustZone. Dokonce ani jádro Linuxu nemá přístup k soukromým klíčům — pouze Keymaster HAL může provádět operace.
Secure Element (např. eSE v Samsung Knox nebo StrongBox v Google Pixel 3+) — je samostatný čip s vlastním procesorem a pamětí. Je certifikován Common Criteria EAL 4+ a poskytuje maximální úroveň ochrany, včetně ochrany proti fyzickému otevření.
| Typ | Místo uložení | Úroveň ochrany | Dostupné od API |
|---|---|---|---|
| Software | Soubor /data/misc/keystore | Střední (AES-256) | API 1+ |
| Keymaster 3 | TEE (TrustZone) | Vysoká | API 23+ |
| Keymaster 4 | TEE + Secure I/O | Velmi vysoká | API 28+ |
| StrongBox | Hardwarový Secure Element | Maximální | API 28+, volitelné |
Android Keystore je integrován do Java Cryptography Architecture (JCA). Pro přístup k poskytovateli se používá standardní KeyStore.getInstance("AndroidKeyStore"). API je dostupné od API 18.
Metoda KeyStore.load(null) načítá kontejner KeyStore aktuální aplikace. Heslo není vyžadováno — Android používá kontext aplikace a její UID k rozlišení přístupu. Každá aplikace vidí pouze své vlastní záznamy, pokud se nepoužívá sdílený UID.
Metody setEntry a getEntry pracují s KeyStore.PrivateKeyEntry, SecretKeyEntry nebo TrustedCertificateEntry. Parametr ProtectionParameter je vždy null pro Android Keystore (ochrana je implementována na úrovni systému).
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)
}
Pomocí KeyCharacteristics lze určit, ve kterém prostředí je klíč uložen: softwarovém KeyStore, TEE nebo StrongBox. Metoda getKeyCharacteristics() vrací sadu příznaků: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometrie).
Android Keystore podporuje širokou škálu kryptografických algoritmů, rozdělenou do tří kategorií: asymetrické, symetrické a MAC. Podpora konkrétních algoritmů závisí na verzi Keymaster HAL.
RSA (1024–4096 bitů) — pro podpis (PKCS1, PSS) a šifrování (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — pro ECDSA podpis a ECDH dohodu. AES (128, 256 bitů) — pro symetrické šifrování v režimech CBC, CTR, GCM. HMAC (SHA1, SHA256, SHA512) — pro autentizaci zpráv.
Pro každý klíč je nastaven setPurposes, který omezuje možné operace. Klíč RSA s PURPOSE_SIGN nelze použít pro šifrování, ani když má útočník přístup k API. Toto je vynucení použití klíče na hardwarové úrovni.
Keymaster obsahuje počítadlo neúspěšných pokusů o biometrickou autentizaci. Po stanoveném počtu neúspěšných pokusů (konfigurovatelném pomocí setInvalidatedByBiometricEnrollment) se klíč stane nedostupným a vyžaduje smazání/regeneraci. Při smazání všech biometrických šablon jsou všechny klíče s userAuthenticationRequired=true automaticky zneplatněny.
Také je podporována Key Attestation (Android 8.1+): na požadavek aplikace Keymaster podepíše certifikát s informacemi o charakteristikách klíče (hardwarový/softwarový, algoritmus, purges). Server může tento certifikát ověřit k potvrzení, že klíč byl vytvořen v důvěryhodném prostředí.
Často kladené otázky
Java KeyStore ukládá klíče v souboru chráněném heslem (JKS, BKS). Android Keystore používá hardwarovou izolaci TEE nebo Secure Element. Java KeyStore je zranitelný při root přístupu, Android Keystore — nikoli, protože soukromé klíče nikdy neopouštějí zabezpečené prostředí.
Ano, prostřednictvím KeyStore.setEntry s KeyProtection. Importovaný klíč však nebude mít hardwarovou ochranu — bude uložen v softwarovém Keystore, zašifrovaném hlavním klíčem. Pro maximální bezpečnost vždy generujte klíče uvnitř Keystore.
Použijte KeyChain.isBoundKeyAlgorithm nebo zkontrolujte KeyCharacteristics po vygenerování klíče. Přítomnost FLAG_HARDWARE v charakteristikách znamená, že klíč byl vytvořen v TEE. Můžete také zkontrolovat android.security.keystore.isHardwareBacked().
Při odinstalaci aplikace Android odstraní všechny její klíče z Keystore. Data jsou nevratně ztracena. Při přeinstalaci musí aplikace vygenerovat nové klíče. Záloha klíčů prostřednictvím TEE je z architektonických důvodů nemožná.
Na uzamčeném zařízení Keymaster neprovádí žádné operace. Klíče s userAuthenticationRequired=true vyžadují každým okamžikem biometrické potvrzení. I s root přístupem nemůže útočník přímo volat Keymaster — pouze prostřednictvím služby Android Keystore.
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é