Android Keystore — is een systeemmechanisme van Android voor veilige opslag van cryptografische sleutels in hardware-isolatie. Het systeem gebruikt Trusted Execution Environment (TEE) op apparaten met ARM TrustZone of een dedicated Secure Element om sleutels op chipniveau te beschermen. Volgens Android Open Source Project ondersteunt Keystore de algoritmen RSA, EC, AES en HMAC met sleutelgeneratie direct in de beveiligde omgeving.
Belangrijkste
Android Keystore — is een cryptografische provider (provider) geïmplementeerd in Android vanaf API 1 (Android 1.0), maar volledige hardware-ondersteuning verscheen met Android 4.3 (API 18). Keystore lost het probleem van veilige opslag van privésleutels op zodanig dat zelfs bij compromittering van het besturingssysteem de aanvaller de sleutels niet in ongecodeerde vorm kan extraheren.
De architectuur van Android Keystore bestaat uit drie lagen: applicatie-API (java.security.KeyStore), systeemdienst (keystore daemon) en hardwarelaag (Keymaster HAL). De applicatie heeft toegang via de standaard Java Cryptography Architecture (JCA) API, en de systeemdienst routeert verzoeken naar Keymaster die in TEE werkt.
Alle cryptografische operaties met sleutels (ondertekenen, ontsleutelen) worden uitgevoerd in TEE of Secure Element. Sleutels verlaten nooit de beveiligde omgeving — de applicatie ontvangt alleen een alias om naar de sleutel te verwijzen. Dit is een fundamenteel verschil met softwarematige KeyStores, waar sleutels potentieel toegankelijk zijn in het procesgeheugen.
Standaard JKS (Java KeyStore) of BKS (Bouncy Castle) slaat sleutels op in met een wachtwoord beveiligde bestanden. Android Keystore slaat sleutels op in hardware-isolatie, waar ze zelfs beschermd zijn tegen de root-gebruiker. JKS is kwetsbaar bij directe toegang tot het bestandssysteem, Android Keystore — niet.
Een ander verschil: in Android Keystore hebben sleutels strikte gebruiksparameters (purpose — alleen sign/verify/encrypt/decrypt) die bij generatie worden ingesteld. Ze kunnen later niet worden gewijzigd, wat misbruik van de sleutel voorkomt.
Bij het maken van een nieuwe sleutel roept de applicatie KeyPairGenerator of KeyGenerator aan met KeyGenParameterSpec, die alle parameters van de toekomstige sleutel bevat. Het systeem stuurt het verzoek naar Keymaster HAL, die de sleutel in TEE genereert en een alias retourneert.
De methode KeyGenParameterSpec.Builder accepteert verplichte parameters: sleutelnaam in Keystore, doel (PURPOSE_SIGN, PURPOSE_ENCRYPT), algoritme (RSA, EC, AES). Aanvullend: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometrie), keyValidityStart/End (tijdsbeperkingen).
Na het instellen van de parameters retourneert KeyPairGenerator.generateKeyPair() een KeyPair, waarbij PrivateKey een object is dat operaties delegeert aan Keymaster. De openbare sleutel kan worden geëxtraheerd, de privésleutel — niet. Deze bestaat alleen in 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 voor ECDSA of RSA-PSS wordt aangemaakt via de standaard API: Signature.getInstance(algorithm).initSign(privateKey). De ondertekeningsoperatie wordt uitgevoerd in TEE: de applicatie stuurt gegevens, Keymaster ondertekent ze hardwarematig en retourneert de handtekening. Sleutel en gegevens worden niet gemengd in het gedeelde geheugen.
Voor biometrische beveiliging is authenticatie van de gebruiker via BiometricPrompt vereist vóór het ondertekenen. Zonder succesvolle authenticatie voert Keymaster de operatie niet uit en retourneert 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 met CryptoObject(signature) vraagt om FaceID/PIN
}
Android ondersteunt twee modi voor sleutelopslag: software (op apparaten zonder TEE) en hardware (op apparaten met TEE of Secure Element). De modus hangt af van de mogelijkheden van de SoC en de Android-versie.
Op apparaten zonder Trusted Execution Environment (vóór Android 4.3 of budget-SoC) worden sleutels opgeslagen in gecodeerde vorm met behulp van een hoofdsleutel afgeleid van het vergrendelschermwachtwoord. Deze modus is minder veilig — sleutels zijn toegankelijk in het procesgeheugen tijdens cryptografische operaties.
Het beveiligingsniveau is gebaseerd op codering van het KeyStore-bestand met AES-256-GCM. De coderingssleutel wordt gegenereerd op basis van het gebruikerswachtwoord of PIN via Scrypt (PBKDF2 met een groot aantal iteraties).
Op moderne apparaten wordt Keymaster 4.x in TEE (ARM TrustZone) gebruikt. Sleutels worden uitsluitend binnen TrustZone gegenereerd, opgeslagen en gebruikt. Zelfs de Linux-kernel heeft geen toegang tot privésleutels — alleen Keymaster HAL kan operaties uitvoeren.
Secure Element (bijv. eSE in Samsung Knox of StrongBox in Google Pixel 3+) — is een aparte chip met eigen processor en geheugen. Het is gecertificeerd volgens Common Criteria EAL 4+ en biedt het maximale beveiligingsniveau, inclusief bescherming tegen fysieke opening.
| Type | Opslaglocatie | Beveiligingsniveau | Beschikbaar vanaf API |
|---|---|---|---|
| Software | Bestand /data/misc/keystore | Gemiddeld (AES-256) | API 1+ |
| Keymaster 3 | TEE (TrustZone) | Hoog | API 23+ |
| Keymaster 4 | TEE + Secure I/O | Zeer hoog | API 28+ |
| StrongBox | Hardware Secure Element | Maximaal | API 28+, optioneel |
Android Keystore is geïntegreerd in Java Cryptography Architecture (JCA). Voor toegang tot de provider wordt standaard KeyStore.getInstance("AndroidKeyStore") gebruikt. De API is beschikbaar vanaf API 18.
De methode KeyStore.load(null) laadt de KeyStore-container van de huidige applicatie. Een wachtwoord is niet vereist — Android gebruikt de applicatiecontext en zijn UID voor toegangsdifferentiatie. Elke applicatie ziet alleen zijn eigen invoer, tenzij een gedeelde UID wordt gebruikt.
De methoden setEntry en getEntry werken met KeyStore.PrivateKeyEntry, SecretKeyEntry of TrustedCertificateEntry. De parameter ProtectionParameter is altijd null voor Android Keystore (beveiliging is geïmplementeerd op systeemniveau).
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)
}
Met KeyCharacteristics kan worden bepaald in welke omgeving de sleutel is opgeslagen: software KeyStore, TEE of StrongBox. De methode getKeyCharacteristics() retourneert een set vlaggen: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometrie).
Android Keystore ondersteunt een brede set cryptografische algoritmen, verdeeld in drie categorieën: asymmetrisch, symmetrisch en MAC. Ondersteuning voor specifieke algoritmen hangt af van de versie van Keymaster HAL.
RSA (1024–4096 bits) — voor ondertekening (PKCS1, PSS) en codering (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — voor ECDSA-handtekening en ECDH-sleuteluitwisseling. AES (128, 256 bits) — voor symmetrische codering in CBC-, CTR- en GCM-modus. HMAC (SHA1, SHA256, SHA512) — voor berichtauthenticatie.
Voor elke sleutel wordt setPuruses ingesteld, die de mogelijke operaties beperkt. Een RSA-sleutel met PURPOSE_SIGN kan niet worden gebruikt voor codering, zelfs niet als de aanvaller toegang heeft tot de API. Dit is handhaving van sleutelgebruik op hardwareniveau.
Keymaster bevat een teller voor mislukte biometrische authenticatiepogingen. Na een ingesteld aantal mislukte pogingen (configureerbaar via setInvalidatedByBiometricEnrollment) wordt de sleutel ontoegankelijk en moet deze worden verwijderd/opnieuw gegenereerd. Bij verwijdering van alle biometrische sjablonen worden alle sleutels met userAuthenticationRequired=true automatisch ongeldig.
Ook wordt Key Attestation (Android 8.1+) ondersteund: op verzoek van de applicatie ondertekent Keymaster een certificaat met informatie over de sleutelkenmerken (hardware/software, algoritme, purges). De server kan dit certificaat verifiëren om te bevestigen dat de sleutel in een vertrouwde omgeving is gemaakt.
Veelgestelde vragen
Java KeyStore slaat sleutels op in een met wachtwoord beveiligd bestand (JKS, BKS). Android Keystore gebruikt hardware-isolatie van TEE of Secure Element. Java KeyStore is kwetsbaar bij root-toegang, Android Keystore — niet, omdat privésleutels nooit de beveiligde omgeving verlaten.
Ja, via KeyStore.setEntry met KeyProtection. De geïmporteerde sleutel heeft echter geen hardwarebeveiliging — deze wordt opgeslagen in de software-Keystore, gecodeerd met de hoofdsleutel. Genereer voor maximale beveiliging altijd sleutels binnen Keystore.
Gebruik KeyChain.isBoundKeyAlgorithm of controleer KeyCharacteristics na het genereren van de sleutel. Aanwezigheid van FLAG_HARDWARE in de kenmerken betekent dat de sleutel in TEE is gemaakt. U kunt ook android.security.keystore.isHardwareBacked() controleren.
Bij het verwijderen van de app verwijdert Android alle sleutels uit Keystore. Gegevens gaan onherroepelijk verloren. Bij herinstallatie moet de app nieuwe sleutels genereren. Back-up van sleutels via TEE is om architectonische redenen onmogelijk.
Op een vergrendeld apparaat voert Keymaster geen operaties uit. Sleutels met userAuthenticationRequired=true vereisen elke keer biometrische bevestiging. Zelfs met root-toegang kan de aanvaller Keymaster niet direct aanroepen — alleen via de Android Keystore-service.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook