Android KeyStore is a secure container for storing cryptographic key material. It prevents key extraction: even if the application process is compromised, an attacker cannot extract keys from the KeyStore, though they may still use them to perform cryptographic operations. Enabling user authentication restricts key usage to authenticated users only, requiring the lock screen to be unlocked with a defined credential (PIN, password, pattern, or biometric).

Why is this an issue?

When cryptographic keys are configured without requiring user authentication, any code running within the application process can use those keys freely. On Android, this happens when a KeyGenParameterSpec.Builder is built without calling setUserAuthenticationRequired(true).

What is the potential impact?

If the application process is compromised, an attacker can use unprotected keys to decrypt sensitive data, forge digital signatures, or impersonate the user without their knowledge. Although the key material itself cannot be extracted from the secure storage, it can still be used to perform cryptographic operations on behalf of the attacker.

How to fix it

Call setUserAuthenticationRequired(true) on the KeyGenParameterSpec.Builder to restrict key use to authenticated users only. The lock screen must be unlocked with a defined credential (PIN, password, pattern, or biometric) before the key can be used. Use setUserAuthenticationParameters to configure the authentication timeout and the accepted credential types; after the timeout expires, the user must re-authenticate.

Code examples

The following code creates a cryptographic key without requiring user authentication, allowing any code running in the application process to use it.

Noncompliant code example

KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

KeyGenParameterSpec builder = new KeyGenParameterSpec.Builder("example-key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) // Noncompliant
    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
    .build();

keyGenerator.init(builder);

Compliant solution

KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

KeyGenParameterSpec builder = new KeyGenParameterSpec.Builder("example-key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
    .setUserAuthenticationRequired(true)
    .setUserAuthenticationParameters (60, KeyProperties.AUTH_DEVICE_CREDENTIAL) // 60 seconds
    .build();

keyGenerator.init(builder);

Resources

Documentation

Standards