Class IdentityCredentialStore
- java.lang.Object
-
- com.android.identity.IdentityCredentialStore
-
public abstract class IdentityCredentialStore extends java.lang.Object
An interface to a secure store for user identity documents.This interface is deliberately fairly general and abstract. To the extent possible, specification of the message formats and semantics of communication with credential verification devices and issuing authorities (IAs) is out of scope. It provides the interface with secure storage but a credential-specific Android application will be required to implement the presentation and verification protocols and processes appropriate for the specific credential type.
The user of these APIs is assumed to be familiar with the ISO/IEC 18013-5:2021 standard, its glossary, and the concepts it introduces.
Multiple credentials can be created. Each credential comprises:
- A document type, which is a string.
- A set of namespaces, which serve to disambiguate value names. It is recommended that namespaces be structured as reverse domain names so that IANA effectively serves as the namespace registrar.
- For each namespace, a set of name/value pairs, each with an associated set of access control profile IDs. Names are strings and values are typed and can be any value supported by CBOR.
- A set of access control profiles, each with a profile ID and a specification of the conditions which satisfy the profile's requirements.
- An asymmetric key pair which is used to authenticate the credential to the Issuing Authority, called the CredentialKey.
- A set of zero or more named reader authentication public keys, which are used to authenticate an authorized reader to the credential.
- A set of named signing keys, which are used to sign collections of values and session transcripts.
Implementing support for user identity documents in secure storage requires dedicated hardware-backed support and may not always be available. In addition to hardware-backed Identity Credential support (which is only available in Android 11 and later and only if the device has support for the Identity Credential HAL), this Jetpack has an Android Keystore backed implementation (also known as the "keystore" implementation) which works on any Android device with API level 24 or later.
The Identity Credential API is designed to be able to evolve and change over time but still provide 100% backwards compatibility. This is complicated by the fact that there may be a version skew between the API used by the application and the version implemented in secure hardware. To solve this problem, the API provides for a way for the application to query for the version of the API implemented in the store through
getFeatureVersion()
. Known feature versions correspond to Android releases and currently includeFEATURE_VERSION_202009
,FEATURE_VERSION_202101
, andFEATURE_VERSION_202201
.The keystore-based store is designed so it implements all capabilities that don't explicitly require hardware features so will always implement the latest feature version defined in this library. Each of the methods in that class will state whether it's implemented in the keystore-based implementation.
When provisioning a document, applications should use either
getHardwareInstance(Context)
orgetKeystoreInstance(Context, File)
to obtain anIdentityCredentialStore
instance and prefer the former if it meets the app's feature version requirement, if any.Apart from hardware- vs keystore-backed, two different flavors of credential stores exist - the default store and the direct access store. Most often credentials will be accessed through the default store but that requires that the Android device be powered up and fully functional. It is desirable to allow identity credential usage when the Android device's battery is too low to boot the Android operating system, so direct access to the secure hardware via NFC may allow data retrieval, if the secure hardware chooses to implement it.
Credentials provisioned to the direct access store should always use reader authentication to protect data elements. The reason for this is user authentication or user approval of data release is not possible when the device is off.
-
-
Field Summary
Fields Modifier and Type Field Description static int
CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256
Specifies that the cipher suite that will be used to secure communications between the reader and the prover is using the following primitives ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111). HKDF-SHA-256 (see RFC 5869). AES-256-GCM (see NIST SP 800-38D). HMAC-SHA-256 (see RFC 2104).static int
FEATURE_VERSION_202009
The feature version corresponding to features included in the Identity Credential API shipped in Android 11.static int
FEATURE_VERSION_202101
The feature version corresponding to features included in the Identity Credential API shipped in Android 12.static int
FEATURE_VERSION_202201
The feature version corresponding to features included in the Identity Credential API shipped in Android 13.static int
FEATURE_VERSION_202301
The feature version corresponding to features included in the Identity Credential API shipped in Android 14.static java.lang.String
IMPLEMENTATION_TYPE_HARDWARE
Specifies that the implementation type of the store is by using Hardware-Backed Identity Credential APIs.static java.lang.String
IMPLEMENTATION_TYPE_KEYSTORE
Specifies that the implementation type of the store is by using Hardware-Backed Android Keystore APIs.
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods Modifier and Type Method Description abstract WritableIdentityCredential
createCredential(java.lang.String credentialName, java.lang.String docType)
Creates a new credential.PresentationSession
createPresentationSession(int cipherSuite)
Creates a new presentation session.abstract byte[]
deleteCredentialByName(java.lang.String credentialName)
Deprecated.UseIdentityCredential.delete(byte[])
instead.abstract IdentityCredential
getCredentialByName(java.lang.String credentialName, int cipherSuite)
Retrieve a named credential.static IdentityCredentialStore
getDirectAccessInstance(android.content.Context context)
Gets theIdentityCredentialStore
for direct access.abstract int
getFeatureVersion()
Returns the feature version implemented by theIdentityCredentialStore
.static IdentityCredentialStore
getHardwareInstance(android.content.Context context)
Gets aIdentityCredentialStore
implemented via secure hardware using the Identity Credential HAL.abstract java.lang.String
getImplementationType()
Returns the type of implementation of the Identity Credential store.static IdentityCredentialStore
getKeystoreInstance(android.content.Context context, java.io.File storageDirectory)
Gets aIdentityCredentialStore
implemented via Hardware-Backed Android Keystore.abstract java.lang.String[]
getSupportedDocTypes()
Gets a list of supported document types.static boolean
isDirectAccessSupported(android.content.Context context)
Checks if direct-access is supported.
-
-
-
Field Detail
-
FEATURE_VERSION_202009
public static final int FEATURE_VERSION_202009
The feature version corresponding to features included in the Identity Credential API shipped in Android 11.- See Also:
- Constant Field Values
-
FEATURE_VERSION_202101
public static final int FEATURE_VERSION_202101
The feature version corresponding to features included in the Identity Credential API shipped in Android 12.This feature version adds support for
IdentityCredential.delete(byte[])
,IdentityCredential.update(PersonalizationData)
,IdentityCredential.proveOwnership(byte[])
, andIdentityCredential.storeStaticAuthenticationData(X509Certificate, Calendar, byte[])
.- See Also:
- Constant Field Values
-
FEATURE_VERSION_202201
public static final int FEATURE_VERSION_202201
The feature version corresponding to features included in the Identity Credential API shipped in Android 13.This feature version adds support for
createPresentationSession(int)
andIdentityCredential.setIncrementKeyUsageCount(boolean)
.- See Also:
- Constant Field Values
-
FEATURE_VERSION_202301
public static final int FEATURE_VERSION_202301
The feature version corresponding to features included in the Identity Credential API shipped in Android 14.This feature version adds support for
IdentityCredential.setAvailableAuthenticationKeys(int, int, long)
andIdentityCredential.getAuthenticationDataExpirations()
.- See Also:
- Constant Field Values
-
CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256
public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256
Specifies that the cipher suite that will be used to secure communications between the reader and the prover is using the following primitives- ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111).
- HKDF-SHA-256 (see RFC 5869).
- AES-256-GCM (see NIST SP 800-38D).
- HMAC-SHA-256 (see RFC 2104).
The exact way these primitives are combined to derive the session key is specified in section 9.2.1.4 of ISO/IEC 18013-5 (see description of cipher suite '1').
At present this is the only supported cipher suite.
- See Also:
- Constant Field Values
-
IMPLEMENTATION_TYPE_HARDWARE
public static final java.lang.String IMPLEMENTATION_TYPE_HARDWARE
Specifies that the implementation type of the store is by using Hardware-Backed Identity Credential APIs.- See Also:
- Constant Field Values
-
IMPLEMENTATION_TYPE_KEYSTORE
public static final java.lang.String IMPLEMENTATION_TYPE_KEYSTORE
Specifies that the implementation type of the store is by using Hardware-Backed Android Keystore APIs.- See Also:
- Constant Field Values
-
-
Method Detail
-
getDirectAccessInstance
@NonNull public static IdentityCredentialStore getDirectAccessInstance(@NonNull android.content.Context context)
Gets theIdentityCredentialStore
for direct access. This should only be called ifisDirectAccessSupported(Context)
returnstrue
.- Parameters:
context
- the application context.- Returns:
- the
IdentityCredentialStore
ornull
if direct access is not supported on this device.
-
isDirectAccessSupported
public static boolean isDirectAccessSupported(@NonNull android.content.Context context)
Checks if direct-access is supported.Direct access requires specialized NFC hardware and may not be supported on all devices even if default store is available.
Because Android is not running when direct-access credentials are presented, there is no way for the user to consent to release of credential data. Therefore, credentials provisioned to the direct access store should always use reader authentication to protect data elements such that only readers authorized by the issuer can access them. The
AccessControlProfile.Builder.setReaderCertificate(X509Certificate)
method can be used at provisioning time to set which reader (or group of readers) are authorized to access data elements.- Parameters:
context
- the application context.- Returns:
true
if direct-access is supported.
-
getFeatureVersion
public abstract int getFeatureVersion()
Returns the feature version implemented by theIdentityCredentialStore
.Note that this may return a feature version which is newer from the version of the library used.
- Returns:
- the feature version.
-
getImplementationType
@NonNull public abstract java.lang.String getImplementationType()
Returns the type of implementation of the Identity Credential store. Known backing types areIMPLEMENTATION_TYPE_HARDWARE
(corresponding to whatgetHardwareInstance(Context)
returns) andIMPLEMENTATION_TYPE_KEYSTORE
(corresponding to whatgetKeystoreInstance(Context, File)
returns).- Returns:
- the type of implementation of the store, either
IMPLEMENTATION_TYPE_HARDWARE
orIMPLEMENTATION_TYPE_KEYSTORE
.
-
getSupportedDocTypes
@NonNull public abstract java.lang.String[] getSupportedDocTypes()
Gets a list of supported document types.Only the direct-access store may restrict the kind of document types that can be used for credentials. The default store always supports any document type.
- Returns:
- The supported document types or the empty array if any document type is supported.
-
createCredential
@NonNull public abstract WritableIdentityCredential createCredential(@NonNull java.lang.String credentialName, @NonNull java.lang.String docType) throws AlreadyPersonalizedException, DocTypeNotSupportedException
Creates a new credential.Note that the credential is not persisted until calling
WritableIdentityCredential.personalize(PersonalizationData)
on the returnedWritableIdentityCredential
object.- Parameters:
credentialName
- The name used to identify the credential.docType
- The document type for the credential.- Returns:
- A
WritableIdentityCredential
that can be used to create a new credential. - Throws:
AlreadyPersonalizedException
- if a credential with the given name already exists.DocTypeNotSupportedException
- if the given document type isn't supported by the store.
-
getCredentialByName
@Nullable public abstract IdentityCredential getCredentialByName(@NonNull java.lang.String credentialName, int cipherSuite) throws CipherSuiteNotSupportedException
Retrieve a named credential.- Parameters:
credentialName
- the name of the credential to retrieve.cipherSuite
- the cipher suite to use for communicating with the verifier.- Returns:
- The named credential, or null if not found.
- Throws:
CipherSuiteNotSupportedException
- if cipher suite is not supported.
-
deleteCredentialByName
@Deprecated @Nullable public abstract byte[] deleteCredentialByName(@NonNull java.lang.String credentialName)
Deprecated.UseIdentityCredential.delete(byte[])
instead.Delete a named credential.This method returns a COSE_Sign1 data structure signed by the CredentialKey with payload set to
ProofOfDeletion
as defined below:ProofOfDeletion = [ "ProofOfDeletion", ; tstr tstr, ; DocType bool ; true if this is a test credential, should ; always be false. ]
- Parameters:
credentialName
- the name of the credential to delete.- Returns:
null
if the credential was not found, the COSE_Sign1 data structure above if the credential was found and deleted.
-
getKeystoreInstance
@NonNull public static IdentityCredentialStore getKeystoreInstance(@NonNull android.content.Context context, @NonNull java.io.File storageDirectory)
Gets aIdentityCredentialStore
implemented via Hardware-Backed Android Keystore. This is also known as the keystore implementation. This implementation guarantees that CredentialKey and all AuthKeys are stored in the Secure Hardware used to back Android Keystore. Additionally, if StrongBox is available it will be used for these kinds of keys.Additionally, with this implementation credential data is stored in the directory specified by the
storageDirectory
parameter. The file names and contents of these files are private to this library and the data stored on disk is encrypted using a hardware-backed symmetric key.The application should choose a path that is not subject to Backup & Restore, for example
getNoBackupFilesDir()
.- Parameters:
context
- The context.storageDirectory
- The path where to storage credential data, see above.- Returns:
- an implementation of
IdentityCredentialStore
implemented on top of Hardware-Backed Android Keystore.
-
getHardwareInstance
@Nullable public static IdentityCredentialStore getHardwareInstance(@NonNull android.content.Context context)
Gets aIdentityCredentialStore
implemented via secure hardware using the Identity Credential HAL.This only works on devices running Android 11 or later and only if the device has support for the Identity Credential HAL.
- Parameters:
context
- The context.- Returns:
- an implementation of
IdentityCredentialStore
implemented in secure hardware ornull
if the device doesn't support the Android Identity Credential HAL.
-
createPresentationSession
@NonNull public PresentationSession createPresentationSession(int cipherSuite) throws CipherSuiteNotSupportedException
Creates a new presentation session.This method gets an object to be used for interaction with a remote verifier for presentation of one or more credentials.
This is only implemented on
FEATURE_VERSION_202201
, fails withUnsupportedOperationException
if using a store with a lesser version.- Parameters:
cipherSuite
- the cipher suite to use for communicating with the verifier.- Returns:
- The presentation session.
- Throws:
CipherSuiteNotSupportedException
- if the cipher suite is not supported.
-
-