Android Keystore — är en systemmekanism i Android för säker lagring av kryptografiska nycklar i hårdvaruisolering. Systemet använder Trusted Execution Environment (TEE) på enheter med ARM TrustZone eller dedikerat Secure Element för att skydda nycklar på chipnivå. Enligt Android Open Source Project stödjer Keystore algoritmerna RSA, EC, AES och HMAC med nyckelgenerering direkt i den skyddade miljön.
Huvudsakligt
Android Keystore — är en kryptografisk leverantör (provider) implementerad i Android från API 1 (Android 1.0), men fullt hårdvarustöd kom med Android 4.3 (API 18). Keystore löser problemet med säker lagring av privata nycklar på ett sådant sätt att även vid kompromettering av operativsystemet kan angriparen inte extrahera nycklarna i öppen form.
Arkitekturen för Android Keystore består av tre nivåer: applikations-API (java.security.KeyStore), systemtjänst (keystore daemon) och hårdvarunivå (Keymaster HAL). Applikationen får åtkomst via standard Java Cryptography Architecture (JCA) API och systemtjänsten dirigerar förfrågningar till Keymaster som arbetar i TEE.
Alla kryptografiska operationer med nycklar (signering, dekryptering) utförs inuti TEE eller Secure Element. Nycklar lämnar aldrig den skyddade miljön — applikationen får endast ett alias för att referera till nyckeln. Detta är en grundläggande skillnad från mjukvaru-KeyStores, där nycklar potentiellt är tillgängliga i processminnet.
Standard JKS (Java KeyStore) eller BKS (Bouncy Castle) lagrar nycklar i lösenordsskyddade filer. Android Keystore lagrar nycklar i hårdvaruisolering, där de är skyddade även från root-användaren. JKS är sårbart vid direkt åtkomst till filsystemet, Android Keystore — inte.
En annan skillnad: i Android Keystore har nycklar strikta användningsparametrar (purpose — endast sign/verify/encrypt/decrypt) som ställs in vid generering. De kan inte ändras i efterhand, vilket förhindrar missbruk av nyckeln.
När en ny nyckel skapas anropar applikationen KeyPairGenerator eller KeyGenerator med KeyGenParameterSpec, som innehåller alla parametrar för den framtida nyckeln. Systemet skickar begäran till Keymaster HAL, som genererar nyckeln inuti TEE och returnerar ett alias.
Metoden KeyGenParameterSpec.Builder accepterar obligatoriska parametrar: nyckelnamn i Keystore, syfte (PURPOSE_SIGN, PURPOSE_ENCRYPT), algoritm (RSA, EC, AES). Tillägg: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometri), keyValidityStart/End (tidsbegränsningar).
Efter att parametrarna har ställts in returnerar KeyPairGenerator.generateKeyPair() ett KeyPair, där PrivateKey är ett objekt som delegerar operationer till Keymaster. Den offentliga nyckeln kan extraheras, den privata — inte. Den finns endast inuti 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 för ECDSA eller RSA-PSS skapas via standard API: Signature.getInstance(algorithm).initSign(privateKey). Signeringsoperationen utförs i TEE: applikationen skickar data, Keymaster signerar dem i hårdvara och returnerar signaturen. Nyckel och data blandas inte i det delade minnet.
För biometriskt skydd krävs autentisering av användaren via BiometricPrompt före signering. Utan framgångsrik autentisering utför Keymaster inte operationen och returnerar 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 med CryptoObject(signature) begär FaceID/PIN
}
Android stödjer två lägen för nyckellagring: mjukvara (på enheter utan TEE) och hårdvara (på enheter med TEE eller Secure Element). Läget beror på SoC:ns kapacitet och Android-versionen.
På enheter utan Trusted Execution Environment (före Android 4.3 eller budget-SoC) lagras nycklar i krypterad form med en huvudnyckel som härrör från låsskärmens lösenord. Detta läge är mindre säkert — nycklar är tillgängliga i processminnet under kryptografiska operationer.
Skyddsnivån baseras på kryptering av KeyStore-filen med AES-256-GCM. Krypteringsnyckeln genereras baserat på användarens lösenord eller PIN via Scrypt (PBKDF2 med stort antal iterationer).
På moderna enheter används Keymaster 4.x i TEE (ARM TrustZone). Nycklar genereras, lagras och används uteslutande inom TrustZone. Även Linux-kärnan har inte tillgång till privata nycklar — endast Keymaster HAL kan utföra operationer.
Secure Element (t.ex. eSE i Samsung Knox eller StrongBox i Google Pixel 3+) — är ett separat chip med egen processor och minne. Det är certifierat enligt Common Criteria EAL 4+ och ger maximal skyddsnivå, inklusive skydd mot fysisk öppning.
| Typ | Lagringsplats | Skyddsnivå | Tillgängligt från API |
|---|---|---|---|
| Software | Fil /data/misc/keystore | Medel (AES-256) | API 1+ |
| Keymaster 3 | TEE (TrustZone) | Hög | API 23+ |
| Keymaster 4 | TEE + Secure I/O | Mycket hög | API 28+ |
| StrongBox | Hårdvaru Secure Element | Maximal | API 28+, valfritt |
Android Keystore är integrerat i Java Cryptography Architecture (JCA). För att få åtkomst till leverantören används standard KeyStore.getInstance("AndroidKeyStore"). API:et är tillgängligt från API 18.
Metoden KeyStore.load(null) laddar KeyStore-behållaren för den aktuella applikationen. Lösenord krävs inte — Android använder applikationskontexten och dess UID för att differentiera åtkomst. Varje applikation ser endast sina egna poster, om inte ett delat UID används.
Metoderna setEntry och getEntry arbetar med KeyStore.PrivateKeyEntry, SecretKeyEntry eller TrustedCertificateEntry. Parametern ProtectionParameter är alltid null för Android Keystore (skyddet är implementerat på systemnivå).
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)
}
Med KeyCharacteristics kan du bestämma i vilken miljö nyckeln lagras: mjukvaru KeyStore, TEE eller StrongBox. Metoden getKeyCharacteristics() returnerar en uppsättning flaggor: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometri).
Android Keystore stödjer en bred uppsättning kryptografiska algoritmer, indelade i tre kategorier: asymmetriska, symmetriska och MAC. Stöd för specifika algoritmer beror på versionen av Keymaster HAL.
RSA (1024–4096 bitar) — för signering (PKCS1, PSS) och kryptering (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — för ECDSA-signering och ECDH-nyckelavtal. AES (128, 256 bitar) — för symmetrisk kryptering i CBC-, CTR-, GCM-lägen. HMAC (SHA1, SHA256, SHA512) — för meddelandeautentisering.
För varje nyckel ställs setPurposes in, som begränsar möjliga operationer. En RSA-nyckel med PURPOSE_SIGN kan inte användas för kryptering, även om angriparen har tillgång till API:et. Detta är tvångsmässig nyckelanvändning på hårdvarunivå.
Keymaster innehåller en räknare för misslyckade biometriska autentiseringsförsök. Efter ett inställt antal misslyckade försök (konfigurerbart via setInvalidatedByBiometricEnrollment) blir nyckeln otillgänglig och kräver borttagning/regenerering. När alla biometriska mallar tas bort, blir alla nycklar med userAuthenticationRequired=true automatiskt ogiltiga.
Även Key Attestation (Android 8.1+) stöds: på begäran av applikationen signerar Keymaster ett certifikat med information om nyckelns egenskaper (hårdvara/mjukvara, algoritm, purges). Servern kan verifiera detta certifikat för att bekräfta att nyckeln skapats i en betrodd miljö.
Vanliga frågor
Java KeyStore lagrar nycklar i en lösenordsskyddad fil (JKS, BKS). Android Keystore använder hårdvaruisolering av TEE eller Secure Element. Java KeyStore är sårbart vid root-åtkomst, Android Keystore — inte, eftersom privata nycklar aldrig lämnar den skyddade miljön.
Ja, via KeyStore.setEntry med KeyProtection. Den importerade nyckeln kommer dock inte att ha hårdvaruskydd — den lagras i mjukvaru-Keystore, krypterad med huvudnyckeln. För maximal säkerhet, generera alltid nycklar inuti Keystore.
Använd KeyChain.isBoundKeyAlgorithm eller kontrollera KeyCharacteristics efter nyckelgenerering. Närvaro av FLAG_HARDWARE i egenskaperna innebär att nyckeln skapades i TEE. Du kan också kontrollera android.security.keystore.isHardwareBacked().
Vid borttagning av appen tar Android bort alla dess nycklar från Keystore. Data förloras oåterkalleligt. Vid ominstallation måste appen Generera nya nycklar. Säkerhetskopiering av nycklar via TEE är omöjligt av arkitektoniska skäl.
På en låst enhet utför Keymaster inga operationer. Nycklar med userAuthenticationRequired=true kräver biometrisk bekräftelse varje gång. Även med root-åtkomst kan angriparen inte anropa Keymaster direkt — endast via Android Keystore-tjänsten.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också