Keystore (Android): cos'è, architettura e principi di funzionamento

Autore: IT Sectr Pubblicato: 2026-03-14 Tempo di lettura: 10 min

Android Keystore è un meccanismo di sistema in Android per archiviare in modo sicuro chiavi crittografiche in isolamento hardware. Il sistema utilizza Trusted Execution Environment (TEE) su dispositivi con ARM TrustZone o un Secure Element dedicato per proteggere le chiavi a livello di chip. Secondo Android Open Source Project, Keystore supporta gli algoritmi RSA, EC, AES e HMAC con generazione di chiavi direttamente nell'ambiente sicuro.

Punti chiave

  • Android Keystore è un provider KeyStore che isola le chiavi crittografiche dallo spazio utente Android
  • Le chiavi vengono generate all'interno di TEE o Secure Element e non lasciano mai l'ambiente sicuro in testo chiaro
  • Android 9+ aggiunge KeyGenParameterSpec.Builder con parametri: purpose, digest, padding, userAuthenticationRequired
  • La protezione biometrica delle chiavi richiede la conferma dell'utente tramite BiometricPrompt prima di ogni operazione
  • Keymaster HAL è un livello di astrazione hardware che implementa operazioni crittografiche in TEE o Secure Element

Cos'è Android Keystore?

Android Keystore è un provider crittografico implementato in Android dall'API 1 (Android 1.0), ma il supporto hardware completo è apparso con Android 4.3 (API 18). Keystore risolve il problema dell'archiviazione sicura delle chiavi private in modo che anche se il sistema operativo viene compromesso, un utente malintenzionato non possa estrarre le chiavi in testo chiaro.

Architettura di KeyStore su Android

L'architettura di Android Keystore è composta da tre livelli: l'API applicativa (java.security.KeyStore), il servizio di sistema (keystore daemon) e il livello hardware (Keymaster HAL). L'applicazione accede tramite l'API standard Java Cryptography Architecture (JCA) e il servizio di sistema instrada le richieste a Keymaster in esecuzione in TEE.

Tutte le operazioni crittografiche con le chiavi (firma, decifratura) vengono eseguite all'interno di TEE o Secure Element. Le chiavi non lasciano mai l'ambiente sicuro — l'applicazione riceve solo un handle (alias) per riferire la chiave. Questa è una differenza fondamentale rispetto ai KeyStore software, dove le chiavi sono potenzialmente accessibili nella memoria del processo.

Differenza da Java KeyStore

Il JKS (Java KeyStore) standard o BKS (Bouncy Castle) archiviano le chiavi in file protetti da password. Android Keystore archivia le chiavi in isolamento hardware, dove sono protette anche dall'utente root. JKS è vulnerabile all'accesso diretto al filesystem; Android Keystore no.

Un'altra differenza: in Android Keystore, le chiavi hanno parametri di utilizzo rigorosi (purpose — solo sign/verify/encrypt/decrypt) specificati al momento della generazione. Non possono essere modificati successivamente, impedendo l'uso improprio della chiave.

Come funziona Android Keystore?

Quando si crea una nuova chiave, l'applicazione chiama KeyPairGenerator o KeyGenerator con KeyGenParameterSpec, che contiene tutti i parametri della chiave futura. Il sistema passa la richiesta a Keymaster HAL, che genera la chiave all'interno di TEE e restituisce un handle.

Processo di generazione della chiave

Il metodo KeyGenParameterSpec.Builder accetta parametri obbligatori: nome della chiave in Keystore, scopo (PURPOSE_SIGN, PURPOSE_ENCRYPT), algoritmo (RSA, EC, AES). Aggiuntivi: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometria), keyValidityStart/End (restrizioni temporali).

Dopo aver impostato i parametri, KeyPairGenerator.generateKeyPair() restituisce un KeyPair, dove PrivateKey è un oggetto che delega le operazioni a Keymaster. La chiave pubblica può essere estratta, quella privata no. Esiste solo all'interno di TEE.

kotlin
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()
}

Firma e verifica

Signature per ECDSA o RSA-PSS viene creata tramite l'API standard: Signature.getInstance(algorithm).initSign(privateKey). L'operazione di firma viene eseguita in TEE: l'applicazione passa i dati, Keymaster li firma hardwaremente e restituisce la firma. La chiave e i dati non si mescolano nella memoria condivisa.

Per la protezione biometrica, l'utente deve essere autenticato tramite BiometricPrompt prima della firma. Senza autenticazione riuscita, Keymaster non esegue l'operazione e restituisce CryptoAuthenticationException.

kotlin
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 con CryptoObject(signature) richiede FaceID/PIN
}

Tipi di archiviazione KeyStore

Android supporta due modalità di archiviazione delle chiavi: software (su dispositivi senza TEE) e hardware (su dispositivi con TEE o Secure Element). La modalità dipende dalle capacità del SoC e dalla versione di Android.

KeyStore software (solo software)

Su dispositivi senza Trusted Execution Environment (precedenti ad Android 4.3 o SoC economici), le chiavi vengono archiviate crittografate utilizzando una chiave master derivata dalla password della schermata di blocco. Questa modalità è meno sicura — le chiavi sono accessibili nella memoria del processo durante le operazioni crittografiche.

Il livello di protezione si basa sulla crittografia del file KeyStore con AES-256-GCM. La chiave di crittografia viene generata dalla password o dal PIN dell'utente tramite Scrypt (PBKDF2 con un numero elevato di iterazioni).

KeyMaster hardware (TEE/Secure Element)

Sui dispositivi moderni, viene utilizzato Keymaster 4.x in TEE (ARM TrustZone). Le chiavi vengono generate, archiviate e utilizzate esclusivamente all'interno di TrustZone. Anche il kernel Linux non ha accesso alle chiavi private — solo Keymaster HAL può eseguire operazioni.

Secure Element (ad esempio, eSE in Samsung Knox o StrongBox in Google Pixel 3+) è un chip separato con proprio processore e memoria. È certificato Common Criteria EAL 4+ e fornisce il massimo livello di protezione, inclusa la protezione contro la manomissione fisica.

TipoPosizione di archiviazioneLivello di protezioneDisponibile da API
SoftwareFile /data/misc/keystoreMedio (AES-256)API 1+
Keymaster 3TEE (TrustZone)AltoAPI 23+
Keymaster 4TEE + Secure I/OMolto altoAPI 28+
StrongBoxSecure Element hardwareMassimoAPI 28+, opzionale

Lavorare con l'API KeyStore

Android Keystore è integrato in Java Cryptography Architecture (JCA). Per accedere al provider, si utilizza KeyStore.getInstance("AndroidKeyStore"). L'API è disponibile dall'API 18.

Creazione e caricamento del KeyStore

Il metodo KeyStore.load(null) carica il contenitore KeyStore dell'applicazione. Non è richiesta alcuna password — Android utilizza il contesto dell'applicazione e il suo UID per il controllo degli accessi. Ogni applicazione vede solo le proprie voci, a meno che non venga utilizzato un UID condiviso.

I metodi setEntry e getEntry funzionano con KeyStore.PrivateKeyEntry, SecretKeyEntry o TrustedCertificateEntry. Il parametro ProtectionParameter è sempre null per Android Keystore (la protezione è implementata a livello di sistema).

kotlin
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)
}

Verifica del tipo di archiviazione

Utilizzando KeyCharacteristics, è possibile determinare in quale ambiente è archiviata la chiave: KeyStore software, TEE o StrongBox. Il metodo getKeyCharacteristics() restituisce un insieme di flag: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometria).

Algoritmi e sicurezza

Android Keystore supporta un'ampia gamma di algoritmi crittografici divisi in tre categorie: asimmetrici, simmetrici e MAC. Il supporto per algoritmi specifici dipende dalla versione di Keymaster HAL.

Algoritmi supportati

RSA (1024–4096 bit) — per firma (PKCS1, PSS) e crittografia (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — per firma ECDSA e accordo chiavi ECDH. AES (128, 256 bit) — per crittografia simmetrica in modalità CBC, CTR, GCM. HMAC (SHA1, SHA256, SHA512) — per autenticazione dei messaggi.

Per ogni chiave, viene specificato setPurposes per limitare le operazioni possibili. Una chiave RSA con PURPOSE_SIGN non può essere utilizzata per la crittografia, anche se un utente malintenzionato ha accesso all'API. Questa è l'applicazione dell'uso della chiave a livello hardware.

Protezione dalla compromissione

Keymaster include un contatore di tentativi di autenticazione biometrica falliti. Dopo un numero specificato di fallimenti (configurabile tramite setInvalidatedByBiometricEnrollment), la chiave diventa non disponibile e richiede eliminazione/rigenerazione. Quando tutti i modelli biometrici vengono rimossi, tutte le chiavi con userAuthenticationRequired=true vengono automaticamente invalidate.

È supportato anche Key Attestation (Android 8.1+): su richiesta dell'applicazione, Keymaster firma un certificato con informazioni sulle caratteristiche della chiave (hardware/software, algoritmo, scopi). Il server può verificare questo certificato per confermare che la chiave è stata creata in un ambiente affidabile.

Domande frequenti

Qual è la differenza tra Android Keystore e Java KeyStore?

Java KeyStore archivia le chiavi in un file protetto da password (JKS, BKS). Android Keystore utilizza l'isolamento hardware tramite TEE o Secure Element. Java KeyStore è vulnerabile all'accesso root; Android Keystore no, perché le chiavi private non lasciano mai l'ambiente sicuro.

Posso importare una chiave esistente in Android Keystore?

Sì, tramite KeyStore.setEntry con KeyProtection. Tuttavia, la chiave importata non avrà protezione hardware — verrà archiviata nel Keystore software, crittografata con una chiave master. Per la massima sicurezza, genera sempre le chiavi all'interno di Keystore.

Come verificare se un dispositivo supporta KeyStore hardware?

Utilizza KeyChain.isBoundKeyAlgorithm o verifica KeyCharacteristics dopo la generazione della chiave. La presenza di FLAG_HARDWARE nelle caratteristiche significa che la chiave è stata creata in TEE. Puoi anche verificare android.security.keystore.isHardwareBacked().

Cosa succede alle chiavi quando l'applicazione viene disinstallata?

Quando l'applicazione viene disinstallata, Android rimuove tutte le sue chiavi dal Keystore. I dati vengono persi irreversibilmente. Alla reinstallazione, l'applicazione deve generare nuove chiavi. Il backup delle chiavi tramite TEE è architetturalmente impossibile.

In che modo KeyStore protegge dagli attacchi di debug?

Su un dispositivo bloccato, Keymaster non esegue alcuna operazione. Le chiavi con userAuthenticationRequired=true richiedono conferma biometrica ogni volta. Anche con accesso root, un utente malintenzionato non può chiamare Keymaster direttamente — solo tramite il servizio Android Keystore.

Riepilogo

  • Android Keystore è un provider crittografico JCA con isolamento hardware delle chiavi tramite TEE o Secure Element
  • Le chiavi vengono generate all'interno di TrustZone e non lasciano mai l'ambiente sicuro in testo chiaro
  • KeyGenParameterSpec definisce i parametri della chiave: purpose, digest, padding, userAuthenticationRequired, keyValidity
  • Keymaster HAL implementa tre livelli: software, TEE (Keymaster 3/4) e StrongBox (Secure Element hardware)
  • La protezione biometrica delle chiavi è fornita tramite setUserAuthenticationRequired e BiometricPrompt con CryptoObject
  • Key Attestation (API 28+) consente la verifica lato server che la chiave sia stata creata in un ambiente hardware
  • Utilizza Android Keystore per archiviare chiavi private per firma, crittografia e autenticazione nelle applicazioni Android

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche