Android Keystore system (original) (raw)

The Android Keystore system lets you store cryptographic keys in a container to make them more difficult to extract from the device. Once keys are in the keystore, you can use them for cryptographic operations, with the key material remaining non-exportable. Also, the keystore system lets you restrict when and how keys can be used, such as requiring user authentication for key use or restricting keys to use only in certain cryptographic modes. See theSecurity Features section for more information.

The keystore system is used by the[KeyChain](/reference/android/security/KeyChain)API, introduced in Android 4.0 (API level 14), as well as the Android Keystore provider feature, introduced in Android 4.3 (API level 18). This document goes over when and how to use the Android Keystore system.

Security features

The Android Keystore system protects key material from unauthorized use in two ways. First, it reduces the risk of unauthorized use of key material from_outside_ the Android device by preventing the extraction of the key material from application processes and from the Android device as a whole. Second, the keystore system reduces the risk of unauthorized use of key material within the Android device by making apps specify the authorized uses of their keys and then enforcing those restrictions outside of the apps' processes.

Key material of Android Keystore keys is protected from extraction using two security measures:

StrongBox KeyMint secure element

Devices running Android 9 (API level 28) or higher can include aStrongBox KeyMint, an implementation of the KeyMint HAL that is backed by StrongBox. While hardware security modules (HSMs) broadly refer to secure key storage solutions resistant to Linux kernel compromises, StrongBox specifically denotes implementations in embedded SEs or integrated Secure Enclaves (iSE), providing stronger isolation and tamper resistance compared to the TEE.

An implementation of StrongBox KeyMint must contain the following:

A subset of algorithms and key sizes are supported to accommodate low-power StrongBox implementations:

StrongBox also supports key attestation.

Use StrongBox KeyMint

Use FEATURE_STRONGBOX_KEYSTORE to check whether StrongBox is available on a device. If StrongBox is available, you can indicate a preference for storing the key in the StrongBox KeyMint by passing true to the following methods:

If the StrongBox KeyMint does not support the specified algorithm or key size, the framework will throw a StrongBoxUnavailableException. If this occurs, generate or import the key without calling setIsStrongBoxBacked(true).

To avoid unauthorized use of keys on the Android device, Android Keystore lets apps specify authorized uses of their keys when they generate or import the keys. Once a key is generated or imported, its authorizations can't be changed. Authorizations are then enforced by the Android Keystore whenever the key is used. This is an advanced security feature that is generally useful only if your requirements are that a compromise of your application process after key generation/import (but not before or during) can't lead to unauthorized uses of the key.

Supported key use authorizations fall into the following categories:

As an additional security measure for keys whose key material is inside secure hardware (seeKeyInfo.isInsideSecurityHardware() or, for apps targeting Android 10 (API level 29) or higher,KeyInfo.getSecurityLevel()), some key use authorizations might be enforced by the secure hardware, depending on the Android device. Secure hardware normally enforces cryptographic and user authentication authorizations. However, secure hardware doesn't usually enforce temporal validity interval authorizations, because it normally doesn't have an independent, secure real-time clock.

You can query whether a key's user authentication authorization is enforced by the secure hardware using[KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware()](/reference/android/security/keystore/KeyInfo#isUserAuthenticationRequirementEnforcedBySecureHardware%28%29).

Choose between a keychain and the Android Keystore provider

Use the [KeyChain](/reference/android/security/KeyChain) API when you want system-wide credentials. When an app requests the use of any credential through the KeyChain API, users can choose, through a system-provided UI, which of the installed credentials an app can access. This lets several apps use the same set of credentials with user consent.

Use the Android Keystore provider to let an individual app store its own credentials, which only that app can access. This provides a way for apps to manage credentials that only they can use while providing the same security benefits that theKeyChain API provides for system-wide credentials. This method doesn't require the user to select the credentials.

Use the Android Keystore provider

To use this feature, you use the standard [KeyStore](/reference/java/security/KeyStore)and [KeyPairGenerator](/reference/java/security/KeyPairGenerator) or[KeyGenerator](/reference/javax/crypto/KeyGenerator) classes along with theAndroidKeyStore provider introduced in Android 4.3 (API level 18).

AndroidKeyStore is registered as a KeyStore type for use with the [KeyStore.getInstance(type)](/reference/java/security/KeyStore#getInstance%28java.lang.String%29) method and as a provider for use with the [KeyPairGenerator.getInstance(algorithm, provider)](/reference/java/security/KeyPairGenerator#getInstance%28java.lang.String, java.lang.String%29) and [KeyGenerator.getInstance(algorithm, provider)](/reference/javax/crypto/KeyGenerator#getInstance%28java.lang.String, java.lang.String%29) methods.

Because cryptographic operations may be time-consuming, apps should avoid usingAndroidKeyStore on their main thread to ensure that the app's UI remains responsive. (StrictMode can help you find places where this is not the case.)

Generate a new private or secret key

To generate a new KeyPair containing a[PrivateKey](/reference/java/security/PrivateKey), you must specify the initial X.509 attributes of the certificate. You can use[KeyStore.setKeyEntry()](/reference/java/security/KeyStore#setKeyEntry%28java.lang.String, java.security.Key, char[], java.security.cert.Certificate[]%29) to replace the certificate at a later time with a certificate signed by a certificate authority (CA).

To generate the key pair, use a [KeyPairGenerator](/reference/java/security/KeyPairGenerator) with [KeyGenParameterSpec](/reference/android/security/keystore/KeyGenParameterSpec):

Kotlin

/*

) val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY ).run { setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) build() }

kpg.initialize(parameterSpec)

val kp = kpg.generateKeyPair()

Java

/*

kpg.initialize(new KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .build());

KeyPair kp = kpg.generateKeyPair();

Import encrypted keys into secure hardware

Android 9 (API level 28) and higher lets you import encrypted keys securely into the keystore using an ASN.1‑encoded key format. The Keymaster then decrypts the keys in the keystore, so the content of the keys never appears as plaintext in the device's host memory. This process provides additional key decryption security.

To support secure importing of encrypted keys into the keystore, complete the following steps:

  1. Generate a key pair that uses thePURPOSE_WRAP_KEYpurpose. We recommend that you add attestation to this key pair as well.
  2. On a server or machine that you trust, generate the ASN.1 message for theSecureKeyWrapper.
    The wrapper contains the following schema:
   KeyDescription ::= SEQUENCE {  
       keyFormat INTEGER,  
       authorizationList AuthorizationList  
   }  
   SecureKeyWrapper ::= SEQUENCE {  
       wrapperFormatVersion INTEGER,  
       encryptedTransportKey OCTET_STRING,  
       initializationVector OCTET_STRING,  
       keyDescription KeyDescription,  
       secureKey OCTET_STRING,  
       tag OCTET_STRING  
   }  
  1. Create aWrappedKeyEntryobject, passing in the ASN.1 message as a byte array.
  2. Pass this WrappedKeyEntry object into the overload ofsetEntry()that accepts aKeystore.Entry object.

Work with keystore entries

You can access the AndroidKeyStore provider through all the standard [KeyStore](/reference/java/security/KeyStore) APIs.

List entries

List entries in the keystore by calling the [aliases()](/reference/java/security/KeyStore#aliases%28%29) method:

Kotlin

/*

Java

/*

Sign and verify data

Sign data by fetching the [KeyStore.Entry](/reference/java/security/KeyStore.Entry) from the keystore and using the[Signature](/reference/java/security/Signature) APIs, such as [sign()](/reference/java/security/Signature#sign%28%29):

Kotlin

/*

Java

/*

Similarly, verify data with the [verify(byte[])](/reference/java/security/Signature#verify%28byte[]%29) method:

Kotlin

/*

Java

/*

Require user authentication for key use

When generating or importing a key into the AndroidKeyStore, you can specify that the key is only authorized to be used if the user has been authenticated. The user is authenticated using a subset of their secure lock screen credentials (pattern/PIN/password, biometric credentials).

This is an advanced security feature that is generally useful only if your requirements are that a compromise of your application process after key generation/import (but not before or during) can't bypass the requirement for the user to be authenticated to use the key.

When a key is only authorized to be used if the user has been authenticated, you can callsetUserAuthenticationParameters()to configure it to operate in one of the following modes:

Authorize for a duration of time

All keys are authorized for use as soon as the user authenticates using one of the credentials specified.

Authorize for the duration of a specific cryptographic operation

Each operation involving a specific key must be individually authorized by the user.

Your app starts this process by callingauthenticate() on an instance of BiometricPrompt.

For each key that you create, you can choose to support astrong biometric credential, alock screen credential, or both types of credentials. To determine whether the user has set up the credentials that your app's key relies on, callcanAuthenticate().

If a key only supports biometric credentials, the key is invalidated by default whenever new biometric enrollments are added. You can configure the key to remain valid when new biometric enrollments are added. To do so, pass false intosetInvalidatedByBiometricEnrollment().

Learn more about how to add biometric authentication capabilities into your app, including how to show a biometric authentication dialog.

Supported algorithms

What's next