Android Fingerprint API



Android Fingerprint API

0 0


gdgfingerprint

Presentation about Android Fingerprint APIs

On Github Mauin / gdgfingerprint

Android Fingerprint API

A crash course in fingerprint authentication

Marvin Ramin

       

What is the Fingerprint API?

 

You are the 0.7%!

Congrationations: You are part of the <0.7 %

It will get better

  • Sony
  • OnePlus
  • Samsung
  • and more Marshmallow updates

It might get better

  • Sony
  • OnePlus
  • Samsung
  • and more Marshmallow updates

Why is fingerprint better than a password?

"Nobody wants to enter a password!"

Nobody wants to open a lock with a key, but wants the door to open once they are close

Passwords suck UX wise

Passwords suck UX wise

  • Forget password
  • Enter password
  • I just want to be authenticated
Your users don't use your app every day I have to interact with the display I want stuff to work automatically Not talking about security

We can do better!

With Code!!

... and hopefully some nice UI

Prequisites

targetSdkVersion 23

USE_FINGERPRINT permission

Device or emulator with fingerprint sensor

Fingerprint Classes

  • FingerprintManager
  • CancellationSignal
  • AuthenticationCallback
  • CryptoObject

FingerprintManager

And forget FingerprintManager again -> FingerprintManagerCompat

FingerprintManagerCompat

Now we can actually use this with pre Marshmallow devices Not use, but it won't crash

FingerprintManagerCompat

return FingerprintManagerCompat.from(context);

FingerprintManagerCompat

  • #authenticate
warms up the fingerprint sensor so it's ready to detect fingers but wait!!

FingerprintManagerCompat

  • #isHardwareDetected
  • #hasEnrolledFingerprints
check if fingerprint authentication is possible

#authenticate(...)

  • CryptoObject
  • flags
  • CancellationSignal
  • AuthenticationCallback
  • Handler
now we're sure fingerprint authentication will work. call authenticate to allow user to use the sensor.

#authenticate(...)

  • (CryptoObject)
  • flags
  • CancellationSignal
  • AuthenticationCallback
  • Handler
CryptoObject - Used for crypto operations related to the authentication More later Optional! Can be null

#authenticate(...)

  • (CryptoObject)
  • (flags)
  • CancellationSignal
  • AuthenticationCallback
  • Handler
"Optional flags, should be 0" - documentation

#authenticate(...)

  • (CryptoObject)
  • (flags)
  • CancellationSignal
  • AuthenticationCallback
  • (Handler)
Handler where callbacks should run Optional, can be null

#authenticate(...)

  • (CryptoObject)
  • (flags)
  • CancellationSignal
  • AuthenticationCallback
  • (Handler)
Create and store this somewhere Cancel operation when not needed anymore Also has callbacks if you want to execute stuff after operation cancelled

#authenticate(...)

  • (CryptoObject)
  • (flags)
  • CancellationSignal
  • AuthenticationCallback
  • (Handler)
This is the big one Callback for results of the authentication

AuthenticationCallback

onAuthentication...

  • Succeeded
  • Error
  • Failed
  • Help

onAuthenticationError

  • Fingerprint detection not possible
  • Operation cancelled
Error is bad, and it will cancel the operation Maybe the sensor is broken, fell out or is just sad today and doesn't want to work Also if operation running too long or too many wrong attempts

onAuthenticationFailed

  • Fingerprint detected but not authenticated
Will not cancel the operation, you can try again Wrong finger, wrong person

onAuthenticationHelp

  • Recoverable error
  • Help string provided
Operation still active Moved finger too fast, too little. Dirt Unclear image Just try again, it will work next time

onAuthenticationSucceeded

  • Fingerprint was detected and authenticated
  • Access to CryptoObject
yay! We have our user (maybe) Any finger registered in the device was found

But what about my UI?

Just build it!

No standard UI exists

Typically a dialog

Must not be a dialog

Use this icon in your UI

"You must implement the user interface for the fingerprint authentication flow on your app, and use the standard Android fingerprint icon in your UI." d.android.com Though you can tint the icon background

UX

Let the user chose to set up fingerprint

Always provide a fallback

Show the user success and error states!

Setup during purchase flow, maybe app start to lock the app Once setup, let the user go back to password!

CryptoObject

now you're encrypting with fingerprints

Fingerprint authentication

...replaces some sort of other authentication

You wouldn't just add fingerprint authentication for the sake of it. User should be present Maybe you still need your old form of authentication for network calls Think password, token, pin, something else Where do you store it?

CryptoObject allows encryption

  • Relies on Android KeyStore
  • Only accessible by biometric authentication
Encryprion and decryption with Android KeyStore Biometric authentication if you set it up correctly

CryptoObject

  • Signature
  • MAC
  • Cipher
Focus on Cipher

CryptoObject

  • Set up Cipher
  • Set up Key in KeyStore
  • Init Cipher with Key
  • Create CryptoObject with Cipher
4 easy steps we will go through

Set up Cipher

return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                + KeyProperties.BLOCK_MODE_CBC + "/"
                + KeyProperties.ENCRYPTION_PADDING_PKCS7
);
4 easy steps we will go through

Set up Key in KeyStore

KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
keyGenerator.init(new KeyGenParameterSpec.Builder(keyName, PURPOSE_ENCRYPT | PURPOSE_DECRYPT)
        .setBlockModes(BLOCK_MODE_CBC)
        .setEncryptionPaddings(ENCRYPTION_PADDING_PKCS7)
        .setUserAuthenticationRequired(true)
        .build());
return keyGenerator.generateKey();

       

Set up Key in KeyStore

KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
keyGenerator.init(new KeyGenParameterSpec.Builder(keyName, PURPOSE_ENCRYPT | PURPOSE_DECRYPT)
        .setBlockModes(BLOCK_MODE_CBC)
        .setEncryptionPaddings(ENCRYPTION_PADDING_PKCS7)
        .setUserAuthenticationRequired(true)
        .build());
return keyGenerator.generateKey();

Or load your Key from the KeyStore

Userauthentication required! Means lock screen authentication Fingerprint required to use this key Don't just create a new key every time or for decryption

Init your Cipher

cipher.init(Cipher.ENCRYPT_MODE, key);
Encrypt mode with the key we just found

Init your Cipher

cipher.init(Cipher.ENCRYPT_MODE, key);
Encrypt mode with the key we just found

Init your Cipher for decryption

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
Decrypt mode and store the Initialization Vector somewhere You can retrieve this after the encryption from the Cipher

Init your Cipher for decryption

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
Decrypt mode and store the Initialization Vector somewhere You can retrieve this after the encryption from the Cipher

Init your Cipher for decryption

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
IV can be stored somewhere. Do not reuse IV's!

Create CryptoObject with Cipher

CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
fingerprintManager.authenticate(cryptoObject, 0, cancellationSignal, callback, null);
Pass this into the .authenticate() call Nothing is encrypted yet! And hope for the succeeded callback!

Create CryptoObject with Cipher

CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
fingerprintManager.authenticate(cryptoObject, 0, cancellationSignal, callback, null);
Pass this into the .authenticate() call Nothing is encrypted yet! And hope for the succeeded callback!

onAuthenticationSucceeded(AuthenticationResult)

Access to the CryptoObject

onAuthenticationSucceeded(AuthenticationResult)

Cipher cipher = authenticationResult.getCryptoObject().getCipher();
byte[] encryptedBytes = cipher.doFinal("1234".getBytes("UTF-8"));

onAuthenticationSucceeded(AuthenticationResult)

Cipher cipher = authenticationResult.getCryptoObject().getCipher();byte[] encryptedBytes = cipher.doFinal("1234".getBytes("UTF-8"));
get access to the cipher

onAuthenticationSucceeded(AuthenticationResult)

Cipher cipher = authenticationResult.getCryptoObject().getCipher();
byte[] encryptedBytes = cipher.doFinal("1234".getBytes("UTF-8"));
Encrypt with the doFinal method Result is encrypted byte array

Quirks & Thoughts

Changing the lockscreen

KeyPermanentlyInvalidatedException

All your encryption keys are invalidated

Makes sense, but is annoying Protects your encrypted data

UX vs. Security

  • Fingerprint != your user
  • Password will be stronger
  • You cannot change your fingerprint
  • But fingerprint sensors are so very convenient

Samples

Thank you!

   @Mauin
1 / 71
Android Fingerprint API A crash course in fingerprint authentication Marvin Ramin