KeyStore (Android): concetti chiave, API e funzionamento dell'archivio crittografico

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

KeyStore (Android) è un'implementazione del provider crittografico Java Cryptography Architecture (JCA) integrata in Android per l'archiviazione sicura delle chiavi con capacità di isolamento hardware. Da Android 4.3 (API 18), KeyStore supporta chiavi hardware tramite Keymaster HAL e, a partire da Android 9 (API 28), StrongBox Keymaster per chiavi in un Secure Element dedicato. Secondo la Documentazione sulla sicurezza Android, il provider “AndroidKeyStore” sostituisce il Bouncy Castle o OpenSSL KeyStore standard, fornendo protezione a livello di sistema contro l'estrazione non autorizzata delle chiavi.

Punti chiave

  • Android KeyStore è un provider JCA per l'archiviazione di chiavi con supporto TEE, StrongBox e protezione biometrica
  • KeyGenParameterSpec definisce algoritmo, scopo, digest, padding e biometria durante la creazione di una chiave
  • Keymaster HAL implementa operazioni crittografiche hardware a livello Software, TEE e StrongBox
  • Key Attestation (API 28+) consente al server di verificare che la chiave sia stata creata in un ambiente hardware Android KeyStore
  • Alias della chiave è una stringa con cui l'applicazione accede alla chiave in Keystore; un alias corrisponde a una chiave

Cos'è KeyStore in Android?

KeyStore in Android non è un'applicazione o un file separato, ma un provider crittografico che implementa l'interfaccia java.security.KeyStore. Fornisce un'API unificata per archiviare e utilizzare chiavi private, chiavi simmetriche e certificati CA attendibili. Il provider è registrato con il nome “AndroidKeyStore” ed è accessibile tramite il KeyStore.getInstance() standard.

Evoluzione di Android KeyStore

Prima di Android 4.3, le operazioni crittografiche venivano eseguite tramite Bouncy Castle. Android 4.3 ha introdotto Keymaster HAL 1.0, consentendo l'uso di TEE su ARM TrustZone. Android 6.0 (API 23) ha aggiunto Keymaster 2.0 con autenticazione biometrica hardware. Android 9 (API 28) ha presentato Keymaster 4.0 e StrongBox Keymaster per un Secure Element dedicato.

Ogni versione di Keymaster aggiunge nuove funzionalità e migliora l'isolamento delle chiavi. I dispositivi moderni (2022+) devono supportare Keymaster 4.0 per la certificazione Google Mobile Services, garantendo la disponibilità di TEE per tutte le applicazioni Android.

Architettura e componenti

Android KeyStore è composto da tre livelli: API Java (KeyStore, KeyPairGenerator), processo di sistema keystore (C++, eseguito come servizio di sistema) e Keymaster HAL (libreria in TEE o Secure Element). L'applicazione chiama l'API, il servizio keystore instrada la richiesta a Keymaster e l'operazione viene eseguita nell'ambiente sicuro.

Tutte le chiavi private sono archiviate in TEE e non possono essere lette dallo spazio utente. Anche il servizio keystore di sistema non ha accesso alle chiavi grezze — solo agli handle che puntano alle chiavi all'interno di Keymaster.

Come funziona KeyStore come provider crittografico?

Android KeyStore implementa l'interfaccia standard del provider di servizi JCA. Quando un'applicazione chiama Cipher.getInstance(“RSA/ECB/PKCS1Padding”, “AndroidKeyStore”), il provider di sicurezza Android delega l'operazione a Keymaster tramite la catena: Java → JNI → servizio keystore → Keymaster HAL.

Registrazione del provider

Il provider AndroidKeyStore viene registrato automaticamente all'avvio del processo. La sua priorità è superiore a quella di Bouncy Castle o Conscrypt. Pertanto, quando si chiama KeyStore.getInstance() senza specificare un provider, nella maggior parte dei casi viene restituito AndroidKeyStore. Per una chiamata esplicita, utilizzare KeyStore.getInstance(“AndroidKeyStore”).

Ogni applicazione Android ha un contenitore isolato in KeyStore. Le applicazioni con lo stesso UID (shared userId) possono condividere l'accesso a determinate chiavi, ma la configurazione standard garantisce che l'applicazione A non possa leggere le chiavi dell'applicazione B.

Metodi di KeyStore e loro particolarità

load(null) — inizializzazione di KeyStore. Il parametro è sempre null per AndroidKeyStore. setEntry — salva una chiave con KeyProtection specificata (scopi, digest, padding). getEntry — recupera KeyStore.PrivateKeyEntry, SecretKeyEntry o TrustedCertificateEntry. containsAlias — verifica se una chiave esiste. deleteEntry — elimina definitivamente una chiave.

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

Algoritmi e tipi di chiave supportati

Android KeyStore supporta un'ampia gamma di algoritmi crittografici, che varia a seconda della versione di Keymaster HAL sul dispositivo. Uno sviluppatore può ottenere l'elenco degli algoritmi supportati tramite KeyGenParameterSpec.Builder durante il tentativo di generazione — i parametri incompatibili generano InvalidAlgorithmParameterException.

Algoritmi asimmetrici

RSA (1024–4096 bit) — per firma (PKCS1, PSS con SHA-1/SHA-256/SHA-384/SHA-512) e crittografia (OAEP con SHA-1/SHA-256). EC (P-224, P-256, P-384, P-521) — per firma ECDSA e accordo chiavi ECDH. X25519 e Ed25519 — da Android 12 (API 31) per protocolli crittografici moderni.

Per le chiavi asimmetriche, genera sempre all'interno di Keymaster, NON importare mai chiavi private. Le chiavi private importate non sono protette hardware — vengono archiviate nel livello software e sono vulnerabili se il processo dell'applicazione viene compromesso.

Algoritmi simmetrici

AES (128, 256 bit) — per crittografia simmetrica in modalità CBC, CTR, GCM. HMAC (SHA-1, SHA-256, SHA-512) — per autenticazione dei messaggi. ChaCha20 (Android 12+) — per crittografia di flusso ad alte prestazioni con autenticazione Poly1305.

AlgoritmoKeymasterScopoAPI
RSAKM 1.0+Firma, Crittografia18+
ECKM 1.0+ECDSA, ECDH18+
AESKM 2.0+Crittografia simmetrica23+
HMACKM 2.0+Codice di autenticazione23+
ChaCha20KM 3.0+Crittografia di flusso31+
X25519/Ed25519KM 3.0+Scambio di chiavi31+

Tipi di chiave e loro serializzazione

KeyStore.PrivateKeyEntry — contiene una chiave privata (non esportabile) e una catena di certificati. KeyStore.SecretKeyEntry — per chiavi simmetriche. KeyStore.TrustedCertificateEntry — per certificati CA attendibili. Le chiavi pubbliche sono esportabili tramite keyStore.getCertificate(alias).publicKey.

Esempi di generazione e utilizzo delle chiavi

Esaminiamo uno scenario completo: generare una chiave AES per la crittografia dei dati e generare una chiave EC per la firma con protezione biometrica. Entrambe le chiavi vengono create all'interno di Android KeyStore con supporto hardware.

Generazione di una chiave AES per la crittografia

Una chiave AES viene creata tramite KeyGenerator con KeyGenParameterSpec. Parametri: PURPOSE_ENCRYPT + PURPOSE_DECRYPT, BLOCK_MODE_GCM (modalità consigliata con autenticazione), ENCRYPTION_PADDING_NONE (nessun padding necessario per GCM).

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

Firma con protezione biometrica

Una chiave EC con userAuthenticationRequired=true richiede l'autenticazione dell'utente prima di ogni operazione di firma. A tale scopo viene utilizzato BiometricPrompt con CryptoObject contenente l'oggetto Signature. Dopo la verifica biometrica riuscita, Keymaster consente l'operazione.

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

KeyStore e sicurezza del dispositivo

Android KeyStore fornisce garanzie di sicurezza a livello hardware che i KeyStore basati su software (JKS, BKS) non possono offrire. Le chiavi sono protette a livello di SoC e anche il controllo completo dello spazio utente Android non consente di estrarre la chiave privata.

Key Attestation (Android 8.1+)

Key Attestation è un meccanismo che consente a un'applicazione (e al server) di verificare l'ambiente in cui è stata creata una chiave. Android Keystore firma un certificato contenente un elenco di caratteristiche della chiave: algoritmo, dimensione, scopi, supporto hardware (True/False), origine (GENERATED, IMPORTED). Il server verifica la catena di certificati fino al certificato root di Google.

Questo è fondamentale per le applicazioni finanziarie: il server può richiedere che la chiave sia stata creata in un ambiente hardware (Hardware-Backed = True) e rifiutare le chiavi create in Keystore software. Key Attestation previene attacchi in cui un utente malintenzionato sostituisce il Keystore con un emulatore.

Invalidazione delle chiavi al cambio dei dati biometrici

setInvalidatedByBiometricEnrollment(true) significa che Keymaster eliminerà automaticamente la chiave quando i modelli biometrici vengono modificati o rimossi. Questo protegge da attacchi in cui un utente malintenzionato aggiunge la propria impronta digitale a un account esistente. Dopo l'aggiunta di una nuova impronta, le chiavi precedenti diventano inaccessibili.

Il contatore dei tentativi falliti di autenticazione biometrica è gestito anch'esso da Keymaster. Dopo maxBiometricAttempt (configurabile dal produttore, generalmente 5), Keymaster blocca tutte le operazioni con chiavi biometriche per 30 secondi. Dopo 10 tentativi falliti — fino all'inserimento della password del dispositivo (PIN segreto).

Domande frequenti

Qual è la differenza tra Android KeyStore e Bouncy Castle KeyStore?

Bouncy Castle (BKS) è un KeyStore basato su software che archivia le chiavi in un file protetto da password. Android KeyStore utilizza l'isolamento hardware TEE/StrongBox. Le chiavi BKS possono essere estratte con accesso root, le chiavi Android KeyStore no. BKS è adatto per certificati CA, Android KeyStore per chiavi private.

Posso usare la stessa chiave per crittografia e firma?

Sì, se specifichi PURPOSE_ENCRYPT o PURPOSE_DECRYPT o PURPOSE_SIGN o PURPOSE_VERIFY al momento della generazione. Tuttavia, la best practice è creare chiavi separate per diverse operazioni. Questo limita il danno se una chiave viene compromessa e segue il principio del minimo privilegio.

Come sapere se una chiave è supportata da hardware in Android KeyStore?

Usa KeyStore.getKeyCharacteristics(alias), disponibile tramite android.security.keystore. Il metodo restituisce un insieme di flag: FLAG_HARDWARE — chiave in TEE, FLAG_SECURE_ELEMENT — chiave in StrongBox. Se non ci sono flag, la chiave è solo software.

Cosa succede quando tutti i modelli biometrici vengono rimossi?

Tutte le chiavi create con setInvalidatedByBiometricEnrollment(true) verranno automaticamente invalidate da Keymaster. Al tentativo di utilizzo, l'applicazione riceverà KeyPermanentlyInvalidatedException. I dati crittografati con queste chiavi andranno persi definitivamente.

Android KeyStore supporta il backup delle chiavi?

Le chiavi hardware (in TEE/StrongBox) non supportano il backup — sono legate a un dispositivo specifico. Le chiavi software possono essere incluse nel backup di Google Drive. Per trasferire dati tra dispositivi, crittografa i dati sul server e decrittografa sul nuovo dispositivo.

Riepilogo

  • Android KeyStore — provider JCA per l'archiviazione di chiavi isolata hardware tramite Keymaster HAL in TEE/StrongBox
  • KeyGenParameterSpec configura algoritmo, dimensione, scopi, digest, biometria e restrizioni temporali della chiave
  • RSA (KM 1.0+), EC (KM 1.0+), AES (KM 2.0+), ChaCha20 (KM 3.0+) — algoritmi supportati con diversi livelli Keymaster
  • Key Attestation (API 28+) consente al server di verificare l'origine hardware della chiave
  • Protezione biometrica delle chiavi tramite setUserAuthenticationRequired + BiometricPrompt con CryptoObject
  • Invalidazione delle chiavi al cambio biometrico impedisce l'uso non autorizzato delle impronte aggiunte
  • Usa Android KeyStore per generare e archiviare chiavi crittografiche con protezione hardware 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