Android: Fingerprint Authentication Thoughts

Manuel Vivo
5 min readOct 9, 2015

--

Introduction

Fingerprint Authentication was one of my projects in a Hackathon organised inside the company I work for (Capital One UK). I had never faced fingerprint authentication before so I thought it could be a good opportunity for me to learn about it.

I only spent few hours on it, but I could get great feedback and thoughts in that time. Let’s see what each class does and what you can do with them.

Apart from the documentation, I got information and a really useful insights mainly from the android-FringerprintDialog project:

Fingerprint Manager

This is the most important class for fingerprint recognition.

You can use FingerprintManager and KeyguardManager to get all the information you need (related to fingerprint authentication) about the device. You can know if the device support fingerprint authentication, if the user has at least one fingerprint enrolled, etc.

# How to instantiate them

KeyguardManager KeyguardManager = getSystemService(KeyguardManager.class);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);

What else you can do? You can tell the FingerprintManager to start listening for fingerprint authentication and get a response if they user completed the action successfully or not. For that, you use the authenticate method.

# Documentation void authenticate(FingerprintManager.CryptoObject crypto, CancellationSignal cancel, int flags, FingerprintManager.AuthenticationCallback callback, Handler handler)
# Usage
fingerprintManager.authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, mAuthenticationCallback, null);

If you see the documentation (and the android-fingerprintDialog project) it takes a FingerprintManager.CryptoObject as a parameter. That parameter can be null!

# UsagefingerprintManager.authenticate(null, mCancellationSignal, 0, mAuthenticationCallback, null);

The CryptoObject makes the process more secure because if that object is not backed by the KeyStore, it’s always going to fail. This object is created by a Cipher which is usually created with a key stored in KeyStore (as you can see in the project).

You can listen for fingerprint authentication without a CryptoObject

You can see what you can get from the Callback in this link. Basically if the user succeeds (apply logic for happy path) or not (display error message, for example).

Different classes can implement the Callback interface. If you are going to use fingerprint authentication to log the user in, you can create a Dialog (as in the example) or you can start listening directly from the LoginFragment (I believe Google suggests displaying a Dialog for fingerprint authentication).

And… That’s it! If you want a simple way of implementing fingerprint authentication, you can use it without a CryptoObject. That means you just get a FingerprintManager instance, call authenticate when you want to start listening for authentication and you’ll get the response in the Callback. Nothing else!

Meaning of other classes in the android-FingerprintDialog project

We talked about CryptoObjects before, this object is associated with the authenticate call. As we said, this can be null. If you don’t want it to be null (for security reasons), you can create it like this:

FingerprintManager.CryptoObject cryptoObject = new  FingerprintManager.CryptoObject(cipher);

For creating the CryptoObject with need a Cipher. If you have your own key stored in the KeyStore then you can initiate it like:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(MY_KEY_NAME, null);
Cipher cipher;
cipher.init(Cipher.ENCRYPT_MODE, key);

If you don’t have a key stored in the KeyStore and you want to, you can do it like this:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");keyStore.load(null);keyGenerator.init(new KeyGenParameterSpec.Builder(MY_KEY_NAME,                                                 KeyProperties.PURPOSE_ENCRYPT |                                                        KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();

We generate the key with the KeyGenerator and we specify that the user authentication is required.

When to create the key? For example, you can create the key when the permission to user fingerprint authentication is granted.

Be aware that the key can be no longer valid (so you have to create a new one) if the user disables the lock screen or resets or adds a new fingerprint after the key was created. You know that it has changed because when you try to initiate the Cipher you get a KeyPermanentlyInvalidatedException.

Different options

There are different ways of using fingerprint authentication. In the project previously mentioned we have a Dialog which processes it. The good thing about the Dialog is that you can customise it and it can look like something like this:

However, you can access to the Android main lock screen and authenticate with that one. The insights are from this other project:

And it looks like:

If you see the project, you launch a new Intent and you get the response onActivityResult. The good thing about this is that you don’t have to worry about the authentication process and you don’t have to handle if the user has fingerprint available or not. If the user doesn’t have it, then this intent will handle it and it won’t show the fingerprint authentication option.

Google recommends using the fingerprint authentication icon provided by them in all your projects. In that way, the user will always know that this method of authentication is available

Conclusion

In this article you can understand a bit better how to use Fingerprint Authentication in a simple way and know more about the different classes that can be used with it.

Thanks for reading,

Manuel Vicente Vivo

--

--