Keystore (Android): What It Is, Architecture and Operating Principles

Author: IT Sectr Published: 2026-03-14 Reading time: 10 min

Android Keystore is a system mechanism in Android for securely storing cryptographic keys in hardware isolation. The system uses Trusted Execution Environment (TEE) on devices with ARM TrustZone or a dedicated Secure Element to protect keys at the chip level. According to Android Open Source Project, Keystore supports RSA, EC, AES and HMAC algorithms with key generation directly in the secure environment.

Key Takeaways

  • Android Keystore is a KeyStore provider that isolates cryptographic keys from Android user space
  • Keys are generated inside TEE or Secure Element and never leave the secure environment in plaintext
  • Android 9+ adds KeyGenParameterSpec.Builder with parameters: purpose, digest, padding, userAuthenticationRequired
  • Biometric key protection requires user confirmation via BiometricPrompt before each operation
  • Keymaster HAL is a hardware abstraction layer that implements cryptographic operations in TEE or Secure Element

What is Android Keystore?

Android Keystore is a cryptographic provider implemented in Android starting from API 1 (Android 1.0), but full hardware support appeared with Android 4.3 (API 18). Keystore solves the problem of secure storage of private keys so that even if the operating system is compromised, an attacker cannot extract keys in plaintext.

KeyStore Architecture on Android

The Android Keystore architecture consists of three layers: the application API (java.security.KeyStore), the system service (keystore daemon), and the hardware level (Keymaster HAL). The application accesses via the standard Java Cryptography Architecture (JCA) API, and the system service routes requests to Keymaster running in TEE.

All cryptographic operations with keys (signing, decryption) are performed inside TEE or Secure Element. Keys never leave the secure environment — the application receives only a handle (alias) to reference the key. This is a fundamental difference from software KeyStores, where keys are potentially accessible in process memory.

Difference from Java KeyStore

Standard JKS (Java KeyStore) or BKS (Bouncy Castle) store keys in password-protected files. Android Keystore stores keys in hardware isolation, where they are protected even from the root user. JKS is vulnerable to direct file system access; Android Keystore is not.

Another difference: in Android Keystore, keys have strict usage parameters (purpose — only sign/verify/encrypt/decrypt) specified at generation time. They cannot be changed later, which prevents key misuse.

How Does Android Keystore Work?

When creating a new key, the application calls KeyPairGenerator or KeyGenerator with KeyGenParameterSpec, which contains all parameters of the future key. The system passes the request to Keymaster HAL, which generates the key inside TEE and returns a handle.

Key Generation Process

The KeyGenParameterSpec.Builder method accepts mandatory parameters: key name in Keystore, purpose (PURPOSE_SIGN, PURPOSE_ENCRYPT), algorithm (RSA, EC, AES). Additional parameters: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (biometrics), keyValidityStart/End (time constraints).

After setting the parameters, KeyPairGenerator.generateKeyPair() returns a KeyPair, where PrivateKey is an object delegating operations to Keymaster. The public key can be extracted, the private key cannot. It exists only inside 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()
}

Signing and Verification

Signature for ECDSA or RSA-PSS is created through the standard API: Signature.getInstance(algorithm).initSign(privateKey). The signing operation is performed in TEE: the application passes data, Keymaster signs it in hardware and returns the signature. The key and data do not mix in shared memory.

For biometric protection, the user must be authenticated via BiometricPrompt before signing. Without successful authentication, Keymaster does not perform the operation and returns 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 with CryptoObject(signature) requests FaceID/PIN
}

KeyStore Storage Types

Android supports two key storage modes: software (on devices without TEE) and hardware (on devices with TEE or Secure Element). The mode depends on SoC capabilities and Android version.

Software KeyStore (software-only)

On devices without Trusted Execution Environment (pre-Android 4.3 or budget SoCs), keys are stored encrypted using a master key derived from the lock screen password. This mode is less secure — keys are accessible in process memory during cryptographic operations.

The protection level is based on KeyStore file encryption using AES-256-GCM. The encryption key is generated from the user's password or PIN via Scrypt (PBKDF2 with a high iteration count).

Hardware KeyMaster (TEE/Secure Element)

On modern devices, Keymaster 4.x in TEE (ARM TrustZone) is used. Keys are generated, stored, and used exclusively inside TrustZone. Even the Linux kernel does not have access to private keys — only Keymaster HAL can perform operations.

Secure Element (e.g., eSE in Samsung Knox or StrongBox in Google Pixel 3+) is a separate chip with its own processor and memory. It is certified Common Criteria EAL 4+ and provides the maximum level of protection, including protection against physical tampering.

TypeStorage LocationProtection LevelAvailable Since API
SoftwareFile /data/misc/keystoreMedium (AES-256)API 1+
Keymaster 3TEE (TrustZone)HighAPI 23+
Keymaster 4TEE + Secure I/OVery HighAPI 28+
StrongBoxHardware Secure ElementMaximumAPI 28+, optional

Working with KeyStore API

Android Keystore is integrated into Java Cryptography Architecture (JCA). To access the provider, the standard KeyStore.getInstance("AndroidKeyStore") is used. The API is available from API 18.

Creating and Loading KeyStore

The KeyStore.load(null) method loads the application's KeyStore container. No password is required — Android uses the application context and its UID for access control. Each application sees only its own entries unless a shared UID is used.

The setEntry and getEntry methods work with KeyStore.PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry. The ProtectionParameter is always null for Android KeyStore (protection is implemented at the system level).

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

Checking Storage Type

Using KeyCharacteristics, you can determine in which environment the key is stored: software KeyStore, TEE, or StrongBox. The getKeyCharacteristics() method returns a set of flags: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (biometrics).

Algorithms and Security

Android Keystore supports a wide range of cryptographic algorithms divided into three categories: asymmetric, symmetric, and MAC. Support for specific algorithms depends on the Keymaster HAL version.

Supported Algorithms

RSA (1024–4096 bits) — for signing (PKCS1, PSS) and encryption (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — for ECDSA signing and ECDH key agreement. AES (128, 256 bits) — for symmetric encryption in CBC, CTR, GCM modes. HMAC (SHA1, SHA256, SHA512) — for message authentication.

For each key, setPurposes is specified to restrict possible operations. An RSA key with PURPOSE_SIGN cannot be used for encryption, even if an attacker has API access. This is hardware-level key usage enforcement.

Compromise Protection

Keymaster includes a counter for failed biometric authentication attempts. After a specified number of failures (configurable via setInvalidatedByBiometricEnrollment), the key becomes unavailable and requires deletion/regeneration. When all biometric templates are removed, all keys with userAuthenticationRequired=true are automatically invalidated.

Key Attestation (Android 8.1+) is also supported: at the application's request, Keymaster signs a certificate with information about the key's characteristics (hardware/software, algorithm, purposes). The server can verify this certificate to confirm that the key was created in a trusted environment.

Frequently Asked Questions

What is the difference between Android Keystore and Java KeyStore?

Java KeyStore stores keys in a password-protected file (JKS, BKS). Android Keystore uses hardware isolation via TEE or Secure Element. Java KeyStore is vulnerable to root access; Android Keystore is not, because private keys never leave the secure environment.

Can I import an existing key into Android Keystore?

Yes, via KeyStore.setEntry with KeyProtection. However, the imported key will not have hardware protection — it will be stored in the software Keystore, encrypted with a master key. For maximum security, always generate keys inside Keystore.

How to check if a device supports hardware KeyStore?

Use KeyChain.isBoundKeyAlgorithm or check KeyCharacteristics after key generation. The presence of FLAG_HARDWARE in the characteristics means the key was created in TEE. You can also check android.security.keystore.isHardwareBacked().

What happens to keys when the application is uninstalled?

When the application is uninstalled, Android removes all its keys from Keystore. The data is irreversibly lost. On reinstallation, the application must generate new keys. Key backup through TEE is architecturally impossible.

How does KeyStore protect against debugging attacks?

On a locked device, Keymaster does not perform any operations. Keys with userAuthenticationRequired=true require biometric confirmation each time. Even with root access, an attacker cannot call Keymaster directly — only through the Android Keystore service.

Summary

  • Android Keystore is a JCA cryptographic provider with hardware key isolation via TEE or Secure Element
  • Keys are generated inside TrustZone and never leave the secure environment in plaintext
  • KeyGenParameterSpec defines key parameters: purpose, digest, padding, userAuthenticationRequired, keyValidity
  • Keymaster HAL implements three levels: software, TEE (Keymaster 3/4), and StrongBox (hardware Secure Element)
  • Biometric key protection is provided via setUserAuthenticationRequired and BiometricPrompt with CryptoObject
  • Key Attestation (API 28+) allows server-side verification that the key was created in a hardware environment
  • Use Android Keystore to store private keys for signing, encryption, and authentication in Android applications

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also