Keystore in Android — cos'è, architettura e crittografia

Autore: IT Sectr Pubblicato: 2026-04-04 Tempo di lettura: 9 min

Android Keystore — un provider crittografico che genera e memorizza chiavi di cifratura in un ambiente di esecuzione isolato (TEE), inaccessibile persino al sistema operativo. Secondo AOSP Security Documentation (2025), oltre l’80% delle app Android nella top 100 di Google Play utilizza Keystore per proteggere token e cifrare dati. Comprendere Android Keystore è fondamentale per la memorizzazione sicura delle chiavi su Android.

Punti chiave

  • Android Keystore — provider di sistema per generare e memorizzare chiavi crittografiche in ambiente hardware isolato (TEE).
  • StrongBox Keymaster — chip di sicurezza dedicato con CPU e TRNG propri, certificato Common Criteria EAL 4+.
  • KeyGenParameterSpec — configuratore per impostare algoritmo, dimensione chiave, binding biometrico e scadenza.
  • TEE (Trusted Execution Environment) — area isolata del processore dove le operazioni crittografiche vengono eseguite senza accesso dallo spazio utente.
  • Le chiavi da Keystore non sono estraibili — la chiave privata non lascia mai TEE o StrongBox, nemmeno lo sviluppatore dell’app può leggerla.

Cos’è Keystore in Android?

Android Keystore — un componente di sistema della piattaforma Android che fornisce API per generare, memorizzare e utilizzare chiavi crittografiche in ambiente protetto. A differenza delle librerie crittografiche software (Bouncy Castle, Conscrypt), Keystore garantisce che le chiavi private non lascino mai l’area di esecuzione isolata.

Keystore è apparso in Android 4.3 (API 18) come provider software con supporto RSA. A partire da Android 6.0 (API 23), Keystore ha ottenuto supporto hardware tramite Keymaster Hardware Abstraction Layer (HAL), che delega le operazioni crittografiche al Trusted Execution Environment (TEE) sui dispositivi compatibili. Secondo il Android Compatibility Definition Document (2025), tutti i dispositivi con Android 9+ devono supportare Keystore hardware tramite TEE o StrongBox.

Le chiavi in Keystore sono identificate da un alias — una stringa passata durante la creazione o il caricamento della chiave. Keystore non permette di ottenere il materiale grezzo della chiave: i metodi getEncoded() restituiscono null per le chiavi create in Keystore. Questa è la differenza fondamentale rispetto alle chiavi software — un attaccante non può estrarre la chiave privata nemmeno con il controllo completo del dispositivo.

Keystore è integrato con altri meccanismi di sicurezza di Android: autenticazione biometrica (BiometricPrompt), cifratura a livello di file (File-Based Encryption) e funzioni di verifica SafetyNet/Play Integrity. Le chiavi possono essere configurate per l’eliminazione automatica a determinate condizioni: alla rimozione del codice di blocco, all’aggiunta di una nuova impronta o alla scadenza.

Architettura di Android Keystore

L’architettura di Android Keystore include tre livelli di implementazione che differiscono per grado di protezione hardware. Il livello dipende dalle capacità hardware del dispositivo.

Keystore supportato da hardware (TEE)

TEE (Trusted Execution Environment) — un’area isolata che opera in parallelo con il sistema operativo principale sullo stesso processore. TEE utilizza la tecnologia ARM TrustZone, che divide il core fisico del processore in due virtuali: Normal World (Android) e Secure World (TEE). Il codice in Secure World ha accesso a memoria e periferiche inaccessibili dal Normal World.

Quando un’app chiama un’operazione crittografica tramite Keystore, la richiesta viene inviata attraverso Keymaster HAL al TEE, dove l’operazione viene eseguita via hardware. Il risultato viene restituito all’app, ma la chiave privata rimane nella memoria protetta del TEE. TEE è certificato conforme al GlobalPlatform TEE Protection Profile ed è un requisito obbligatorio per i dispositivi Android 9+ con processori che supportano TrustZone.

TEE supporta gli algoritmi AES/GCM (128, 256 bit), RSA (2048, 4096 bit), EC (P-256, P-384, P-521) e HMAC-SHA256. Le prestazioni di TEE sono inferiori alla crittografia software (dal 20 al 40% in meno), ma per le operazioni tipiche (firma JWT, decifratura chiave di sessione) la latenza non supera 10–50 ms.

StrongBox Keymaster

StrongBox — un chip di sicurezza dedicato, fisicamente separato dal processore principale. A differenza di TEE, che condivide il tempo del processore con Android, StrongBox ha CPU, RAM, True Random Number Generator (TRNG) e memoria protetta (One-Time Programmable memory) propri. StrongBox è certificato Common Criteria EAL 4+ e Secure IC Protection Profile.

StrongBox è disponibile sui dispositivi con Android 9+ in presenza del chip corrispondente (ad esempio, Titan M su Google Pixel, Knox su Samsung Galaxy). Lo sviluppatore abilita StrongBox tramite il flag setIsStrongBoxBacked(true) in KeyGenParameterSpec. In assenza di supporto hardware, il flag viene ignorato e Keystore passa a TEE.

Limitazioni di StrongBox: supporta un insieme limitato di algoritmi (AES-256, EC P-256, HMAC-SHA256), coda operazioni — massimo una alla volta, numero di operazioni — limitato dalle risorse del chip. StrongBox non è progettato per scenari ad alto carico — usa TEE per operazioni frequenti e StrongBox solo per chiavi critiche (chiavi master di cifratura, chiavi di firma).

Keystore software

Keystore software — implementazione software utilizzata su dispositivi senza supporto hardware TEE o StrongBox. Le chiavi sono memorizzate in forma cifrata nel filesystem, ma la chiave privata può essere temporaneamente decifrata in RAM. Keystore software è meno sicuro — un attaccante con accesso root può intercettare la chiave in memoria.

A partire da Android 12 (API 31), Google richiede il supporto hardware Keystore per tutti i nuovi dispositivi. I dispositivi con Android 9–11 possono avere Keystore software sui modelli economici. Lo sviluppatore può verificare il livello di protezione tramite KeyStore.getKeyCharacteristics() — l’attributo SECURITY_LEVEL_TRUSTED_ENVIRONMENT o SECURITY_LEVEL_STRONGBOX conferma la protezione hardware.

Algoritmi e funzioni supportati

Android Keystore supporta un’ampia gamma di algoritmi crittografici, suddivisi in categorie in base al tipo di chiave. La scelta dell’algoritmo influenza prestazioni, compatibilità e livello di sicurezza.

AES (Advanced Encryption Standard) — cifratura simmetrica per proteggere i dati sul dispositivo. Modalità consigliata: AES/GCM/NoPadding (256 bit). GCM fornisce cifratura autenticata (AEAD) — verifica dell’integrità dei dati cifrati. Dimensione IV (Initialization Vector) per GCM: 12 byte. Non utilizzare AES/ECB — non fornisce una protezione adeguata.

RSA (Rivest–Shamir–Adleman) — cifratura asimmetrica per proteggere chiavi di sessione e firma digitale. Dimensione consigliata: 2048 o 4096 bit. Modalità: RSA/ECB/PKCS1Padding (cifratura) e RSA/ECB/PKCS1Sign (firma). RSA 1024 è considerato obsoleto e non raccomandato per nuove applicazioni (NIST SP 800-131A Rev. 2).

EC (Elliptic Curve) — crittografia asimmetrica a curve ellittiche per firma e scambio di chiavi. Curve supportate: secp256r1 (P-256, obbligatoria), secp384r1 (P-384) e secp521r1 (P-521). EC fornisce sicurezza equivalente a RSA con dimensione della chiave significativamente inferiore. P-256 è raccomandato per la maggior parte degli scenari: è supportato da tutti i dispositivi e offre un livello di sicurezza a 128 bit.

HMAC (Hash-based Message Authentication Code) — autenticazione simmetrica dei messaggi. Funzioni di hash supportate: SHA-256, SHA-384, SHA-512. HMAC viene utilizzato per verificare l’integrità e l’autenticità dei dati, ad esempio per la verifica delle richieste webhook o il controllo dell’integrità della configurazione.

Tutti gli algoritmi possono essere vincolati all’autenticazione biometrica tramite KeyGenParameterSpec.Builder.setUserAuthenticationRequired(true). Su Android 11+ è disponibile il flag setUserAuthenticationParameters() con specifica del timeout (in secondi) durante il quale la chiave è disponibile dopo l’autenticazione biometrica senza richiederla nuovamente.

Esempi di codice: generazione e uso delle chiavi

Vediamo esempi pratici con Android Keystore in Kotlin: generazione di una chiave AES, cifratura dei dati e creazione di una coppia asimmetrica per la firma.

Generazione di una chiave AES in Keystore

L’esempio crea una chiave AES/GCM a 256 bit con vincolo biometrico. La chiave non può essere esportata tramite getEncoded().

kotlin
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore

private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }

fun generateAesKey(alias: String) {
    val spec = KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_ENCRYPT or
        KeyProperties.PURPOSE_DECRYPT
    )
    .setKeySize(256)
    .setBlockModes(KeyProperties.KEY_BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
    .setUserAuthenticationRequired(true)
    .setInvalidatedByBiometricEnrollment(true)
    .build()

    val generator = KeyGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_AES,
        "AndroidKeyStore"
    )
    generator.init(spec)
    generator.generateKey()
}

Cifratura dati AES/GCM

L’esempio cifra i dati utilizzando una chiave da Android Keystore. Cipher ottiene la chiave tramite alias, inizializza la cifratura AES/GCM e restituisce i dati cifrati insieme all’IV.

kotlin
fun encryptData(alias: String, plaintext: ByteArray): ByteArray {
    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    val secretKey = keyStore.getKey(alias, null) as SecretKey
    cipher.init(Cipher.ENCRYPT_MODE, secretKey)

    val iv = cipher.getIV()
    val encrypted = cipher.doFinal(plaintext)

    // IV + dati cifrati
    return iv + encrypted
}

fun decryptData(alias: String, ciphertextWithIv: ByteArray): ByteArray {
    val iv = ciphertextWithIv.copyOfRange(0, 12)
    val encrypted = ciphertextWithIv.copyOfRange(12, ciphertextWithIv.size)

    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    val secretKey = keyStore.getKey(alias, null) as SecretKey
    val spec = GCMParameterSpec(128, iv)
    cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)

    return cipher.doFinal(encrypted)
}

Generazione di una coppia RSA per la firma

L’esempio crea una coppia di chiavi RSA-2048 in Keystore con vincolo StrongBox. La chiave privata viene utilizzata per la firma, quella pubblica può essere esportata tramite getEncoded().

kotlin
fun generateRsaKeyPair(alias: String) {
    val spec = KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_SIGN or
        KeyProperties.PURPOSE_VERIFY
    )
    .setKeySize(2048)
    .setSignaturePaddings(
        KeyProperties.SIGNATURE_PADDING_RSA_PKCS1
    )
    .setDigests(KeyProperties.DIGEST_SHA256)
    .setIsStrongBoxBacked(true)
    .build()

    val pair = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_RSA,
        "AndroidKeyStore"
    ).apply { init(spec) }
     .generateKeyPair()

    // La chiave pubblica può essere esportata
    val publicKey = pair.public // X509EncodedKeySpec
}

Buone pratiche con Android Keystore

L’uso efficace di Android Keystore richiede il rispetto di regole che garantiscono la massima protezione mantenendo le prestazioni.

Utilizza KeyGenParameterSpec con i parametri minimi necessari: specifica solo i purpose, block modes e paddings effettivamente utilizzati. Parametri eccessivi (ad esempio, PURPOSE_ENCRYPT per una chiave usata solo per la firma) creano vettori di attacco superflui. Android raccomanda di specificare esplicitamente il digest per la firma — SHA256 è il livello minimo accettabile (SHA1 è obsoleto).

Vincola le chiavi alla biometria per le operazioni critiche: setUserAuthenticationRequired(true) garantisce che la chiave possa essere usata solo dopo l’autenticazione biometrica. Su Android 11+ utilizza setUserAuthenticationParameters() con un timeout (consigliato 30–60 secondi) per non richiedere la biometria per ogni operazione nella stessa sessione. setInvalidatedByBiometricEnrollment(true) elimina automaticamente la chiave all’aggiunta di una nuova impronta o volto — impedisce l’accesso tramite dati biometrici vecchi.

Controlla il livello di sicurezza in fase di inizializzazione: utilizza KeyStore.getKeyCharacteristics() per determinare SECURITY_LEVEL. Se il dispositivo supporta solo Keystore software (SECURITY_LEVEL_SOFTWARE), decidi se rifiutare la funzionalità o utilizzare una cifratura aggiuntiva (ad esempio, wrapping della chiave tramite password utente). Non fare affidamento su StrongBox se non è garantito — specifica sempre il flag setIsStrongBoxBacked(true) e verifica il risultato tramite getKeyCharacteristics.

Aggiorna le chiavi secondo programma: le chiavi crittografiche hanno una durata di vita consigliata. NIST SP 800-57 raccomanda di cambiare le chiavi AES ogni 1–2 anni, le coppie RSA/EC ogni 2–3 anni. Implementa un meccanismo di rotazione delle chiavi: all’avvio dell’app controlla la data di creazione della chiave (KeyGenParameterSpec.Builder.setKeyValidityStart/End) e genera una nuova chiave alla scadenza. I vecchi dati cifrati con la vecchia chiave devono essere decifrati e ricifrati con la nuova.

Non utilizzare Keystore per dati grandi: Keystore è progettato per memorizzare chiavi (poche centinaia di byte), non per cifrare file di grandi dimensioni. Per la cifratura dei dati utilizza lo schema: genera una chiave AES casuale (DEK — Data Encryption Key), cifra i dati con questa chiave, e cifra DEK con la chiave Keystore (KEK — Key Encryption Key). Android EncryptedSharedPreferences utilizza proprio questo schema: chiave master in Keystore, dati — AES-256 GCM.

Domande frequenti

È possibile ottenere la chiave privata da Android Keystore?

No, Android Keystore è progettato in modo che la chiave privata non lasci mai TEE o StrongBox. Il metodo getEncoded() restituisce null per le chiavi create in Keystore. La chiave può essere utilizzata solo tramite Cipher, Signature o Mac API — il materiale grezzo non è disponibile.

Qual è la differenza tra TEE e StrongBox?

TEE (TrustZone) — isolamento virtuale sullo stesso processore, utilizza la divisione temporale. StrongBox — chip separato con CPU e memoria propri. StrongBox è più sicuro (Common Criteria EAL 4+), ma più lento e supporta meno algoritmi. TEE è adatto per operazioni frequenti, StrongBox per chiavi critiche.

Come verificare se il dispositivo supporta StrongBox?

Utilizza KeyStore.getKeyCharacteristics() dopo la generazione della chiave con il flag setIsStrongBoxBacked(true). L’attributo SECURITY_LEVEL_STRONGBOX conferma il supporto hardware. Se il dispositivo non supporta StrongBox, Keystore passa a TEE senza errore — è necessario verificare esplicitamente il livello di sicurezza.

Cosa succede alle chiavi quando si disinstalla l’app?

Le chiavi in Keystore vengono eliminate automaticamente alla disinstallazione dell’app dal dispositivo. Su Android 10+ le chiavi possono essere conservate se l’app ha il flag allowBackup=true nel manifest, ma non saranno disponibili dopo la reinstallazione. Si consiglia di rigenerare le chiavi in caso di installazione pulita.

Si può usare una chiave su più dispositivi?

No, Android Keystore è legato all’hardware del dispositivo specifico. Una chiave generata nel TEE di un dispositivo non può essere trasferita a un altro. Per la cifratura multipiattaforma utilizza lo schema: Keystore protegge la chiave sul dispositivo, e le chiavi di sessione vengono trasmesse tramite API sicura utilizzando cifratura asimmetrica.

Riepilogo

  • Android Keystore — provider di sistema per la protezione delle chiavi crittografiche in ambiente hardware isolato (TEE o StrongBox).
  • TEE (TrustZone) — isolamento virtuale sullo stesso processore, obbligatorio per Android 9+ su dispositivi con TrustZone.
  • StrongBox — chip di sicurezza dedicato con certificazione Common Criteria EAL 4+, abilitato tramite setIsStrongBoxBacked(true).
  • KeyGenParameterSpec — classe centrale per la configurazione dei parametri della chiave: algoritmo, dimensione, vincolo biometrico e rotazione.
  • Chiavi non estraibili — materiale privato non disponibile tramite getEncoded(), operazioni eseguite all’interno di TEE/StrongBox.
  • Algoritmi consigliati — AES/GCM/NoPadding (256 bit) per cifratura, EC P-256 per firma, RSA 2048 per scenari asimmetrici.
  • Schema KEK/DEK — Keystore memorizza la chiave master per proteggere le chiavi di cifratura dei dati, garantendo prestazioni e sicurezza.

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