Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Overview of Biometric Auth

Overview of Biometric Auth

Avatar for Michael Bailey

Michael Bailey

October 24, 2019
Tweet

More Decks by Michael Bailey

Other Decks in Programming

Transcript

  1. NOT SECURITY ADVICE Information in this talk should not be

    taken as security advice.The security needs of every application are different. Consult an InfoSec professional when designing and implementing security for your application.
  2. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ package android.hardware.fingerprint; public

    class FingerprintManager { public boolean isHardwareDetected() public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) }
  3. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ val fp: FingerprintManager

    = requireContext() .getSystemService(FingerprintManager'(class.java)
  4. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ if (Build.VERSION.SDK_INT )*

    23) { val fp: FingerprintManager = requireContext() .getSystemService(FingerprintManager'(class.java) … }
  5. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ package android.hardware.fingerprint; public

    class FingerprintManager { public boolean isHardwareDetected() public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } public boolean isHardwareDetected()
  6. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ if (Build.VERSION.SDK_INT )*

    23) { val fp: FingerprintManager = requireContext() .getSystemService(FingerprintManager'(class.java) if (fp.isHardwareDetected) { !" Some low end devices don’t have fingerprint sensor !" or sensor can’t be used to unlock keys } } if (fp.isHardwareDetected) { !" Some low end devices don’t have fingerprint sensor !" or sensor can’t be used to unlock keys
  7. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ package android.hardware.fingerprint; public

    class FingerprintManager { public boolean isHardwareDetected() public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } public boolean hasEnrolledFingerprints()
  8. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ if (Build.VERSION.SDK_INT )*

    23) { val fp: FingerprintManager = requireContext() .getSystemService(FingerprintManager'(class.java) if (fp.isHardwareDetected) { if (fp.hasEnrolledFingerprints()){ fp.authenticate(+,-) } else { !" tell user to go setup fingerprints in OS settings } } } if (fp.hasEnrolledFingerprints()){
  9. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ Caused by: java.lang.SecurityException:

    Permission Denial: getCurrentUser() from pid=12045, uid=10028 r android.permission.INTERACT_ACROSS_USERS at android.os.Parcel.readException(Parcel.java:1620) at android.os.Parcel.readException(Parcel.java:1573) at android.hardware.fingerprint. IFingerprintService$Stub$Proxy.hasEnrolledFingerprints(IFingerpr at android.hardware.fingerprint. FingerprintManager.hasEnrolledFingerprints(FingerprintManager.ja java.lang.SecurityException: FingerprintManager.hasEnrolledFingerprints
  10. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ if (Build.VERSION.SDK_INT )*

    23) { val fp: FingerprintManager = requireContext() .getSystemService(FingerprintManager'(class.java) if (fp.isHardwareDetected) { if (fp.hasEnrolledFingerprints()){ +,- } else { !" tell user to go setup fingerprints in OS settings } } } if (fp.hasEnrolledFingerprints()){ !" tell user to go setup fingerprints in OS settings
  11. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ package android.hardware.fingerprint; public

    class FingerprintManager { public boolean isHardwareDetected() public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler)
  12. if (Build.VERSION.SDK_INT )* 23) { val fp: FingerprintManager = requireContext()

    .getSystemService(FingerprintManager'(class.java) if (fp.isHardwareDetected) { if (fp.hasEnrolledFingerprints()){ fp.authenticate(+,-) } else { !" tell user to go setup fingerprints in OS settings } } } fp.authenticate(+,-) “LEGACY” FINGERPRINT MANAGER APIS - API 23+
  13. “LEGACY” FINGERPRINT MANAGER APIS - API 23+ package android.hardware.fingerprint; public

    class FingerprintManager { public boolean isHardwareDetected() public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler)
  14. android.os.CancellationSignal package android.hardware.fingerprint; public class FingerprintManager { public boolean isHardwareDetected()

    public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } @Nullable CancellationSignal cancel,
  15. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public boolean isHardwareDetected()

    public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } int flags,
  16. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public boolean isHardwareDetected()

    public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } Handler handler
  17. CryptoObject package android.hardware.fingerprint; public class FingerprintManager { public boolean isHardwareDetected()

    public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } @Nullable CryptoObject crypto
  18. CryptoObject package android.hardware.fingerprint; public class FingerprintManager { public static final

    class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public Signature getSignature() {…} public Cipher getCipher() {…} public Mac getMac() {…} } } public static final class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public java.security.Signature getSignature() {…} public javax.crypto.Cipher getCipher() {…} public javax.crypto.Mac getMac() {…} }
  19. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public boolean isHardwareDetected()

    public boolean hasEnrolledFingerprints() public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler) } @NonNull AuthenticationCallback callback
  20. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public static abstract

    class AuthenticationCallback { public void onAuthenticationError(int errorCode, CharSequence errString) public void onAuthenticationHelp(int helpCode, CharSequence helpString) public void onAuthenticationFailed() public void onAuthenticationSucceeded(AuthenticationResult result) } } AuthenticationCallback onAuthenticationError
  21. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public static abstract

    class AuthenticationCallback { public void onAuthenticationError(int errorCode, CharSequence errString) public void onAuthenticationHelp(int helpCode, CharSequence helpString) public void onAuthenticationFailed() public void onAuthenticationSucceeded(AuthenticationResult result) } } AuthenticationCallback onAuthenticationHelp
  22. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public static abstract

    class AuthenticationCallback { public void onAuthenticationError(int errorCode, CharSequence errString) public void onAuthenticationHelp(int helpCode, CharSequence helpString) public void onAuthenticationFailed() public void onAuthenticationSucceeded(AuthenticationResult result) } } AuthenticationCallback onAuthenticationFailed
  23. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public static abstract

    class AuthenticationCallback { public void onAuthenticationError(int errorCode, CharSequence errString) public void onAuthenticationHelp(int helpCode, CharSequence helpString) public void onAuthenticationFailed() public void onAuthenticationSucceeded(AuthenticationResult result) } } AuthenticationCallback onAuthenticationSucceeded(AuthenticationResult result)
  24. FingerprintManager.authenticate() package android.hardware.fingerprint; public class FingerprintManager { public static class

    AuthenticationResult { public CryptoObject getCryptoObject() } } public static class AuthenticationResult { public CryptoObject getCryptoObject() }
  25. CryptoObject package android.hardware.fingerprint; public class FingerprintManager { public static final

    class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public Signature getSignature() {…} public Cipher getCipher() {…} public Mac getMac() {…} } } public static final class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public java.security.Signature getSignature() {…} public javax.crypto.Cipher getCipher() {…} public javax.crypto.Mac getMac() {…} }
  26. BIOMETRIC PROMPT APIS - API 28+ package android.hardware.biometrics; public class

    BiometricPrompt { public static class Builder { public Builder(Context) public Builder setTitle(CharSequence) public Builder setSubtitle(CharSequence) public Builder setDescription(CharSequence) public Builder setNegativeButton(CharSequence) public Builder setConfirmationRequired(boolean) !" API 29 public Builder setDeviceCredentialAllowed(boolean) !" API 29 public BiometricPrompt build() } public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Executor executor, @NonNull AuthenticationCallback callback) }
  27. BIOMETRIC PROMPT APIS - API 28+ package android.hardware.biometrics; public class

    BiometricPrompt { public static class Builder { public Builder(Context) public Builder setTitle(CharSequence) public Builder setSubtitle(CharSequence) public Builder setDescription(CharSequence) public Builder setNegativeButton(CharSequence) public Builder setConfirmationRequired(boolean) public Builder setDeviceCredentialAllowed(boolean) public BiometricPrompt build() } public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Executor executor, @NonNull AuthenticationCallback callback) } public BiometricPrompt build()
  28. BIOMETRIC PROMPT APIS - API 28+ package android.hardware.biometrics; public class

    BiometricPrompt { public static class Builder { public Builder(Context) public Builder setTitle(CharSequence) public Builder setSubtitle(CharSequence) public Builder setDescription(CharSequence) public Builder setNegativeButton(CharSequence) public Builder setConfirmationRequired(boolean) public Builder setDeviceCredentialAllowed(boolean) public BiometricPrompt build() } public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Executor executor, @NonNull AuthenticationCallback callback) } @NonNull Executor executor, authenticate(
  29. BIOMETRIC PROMPT APIS - API 28+ package android.hardware.biometrics; public class

    BiometricPrompt { public static class Builder { public Builder(Context) public Builder setTitle(CharSequence) public Builder setSubtitle(CharSequence) public Builder setDescription(CharSequence) public Builder setNegativeButton(CharSequence) public Builder setConfirmationRequired(boolean) public Builder setDeviceCredentialAllowed(boolean) public BiometricPrompt build() } public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Executor executor, @NonNull AuthenticationCallback callback) } authenticate(
  30. BIOMETRIC PROMPT APIS - API 28+ package android.hardware.biometrics; public class

    BiometricPrompt { public static class Builder { public Builder(Context) public Builder setTitle(CharSequence) public Builder setSubtitle(CharSequence) public Builder setDescription(CharSequence) public Builder setNegativeButton(CharSequence) public Builder setConfirmationRequired(boolean) !" API 29+ public Builder setDeviceCredentialAllowed(boolean) !" API 29+ public BiometricPrompt build() } public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Executor executor, @NonNull AuthenticationCallback callback) }
  31. BIOMETRIC PROMPT APIS - API 29+ package android.hardware.biometrics; public class

    BiometricManager { @IntDef({BIOMETRIC_SUCCESS, BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED, BIOMETRIC_ERROR_NO_HARDWARE}) @interface BiometricError {} public @BiometricError int canAuthenticate() }
  32. BIOMETRIC PROMPT APIS if (VERSION.SDK_INT )* VERSION_CODES.Q) { val biometricManager

    = this.getSystemService(BiometricManager'(class.java) when (biometricManager.canAuthenticate()) { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val biometricPrompt = BiometricPrompt.Builder(this) .setTitle("Login") .build() biometricPrompt.authenticate(+,-) } } }
  33. CHALLENGES • FingerprintManager • API 23+ • No UI provided

    • no Iris or Face Auth • BiometricPrompt • API 28+ • Provides a UI • BiometricManager.canAuthenticate() only API 29+
  34. androidx.biometric - API 14+ val biometricManager = BiometricManager.from(context) when (biometricManager.canAuthenticate())

    { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Login") .build() val biometricPrompt = BiometricPrompt(fragmentActivity, executor, authenticationCallback) biometricPrompt.authenticate(promptInfo, cryptoObject) } } BiometricManager.from(context)
  35. androidx.biometric - API 14+ val biometricManager = BiometricManager.from(context) when (biometricManager.canAuthenticate())

    { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Login") .build() val biometricPrompt = BiometricPrompt(fragmentActivity, executor, authenticationCallback) biometricPrompt.authenticate(promptInfo, cryptoObject) } } biometricManager.canAuthenticate()
  36. androidx.biometric - API 14+ val biometricManager = BiometricManager.from(context) when (biometricManager.canAuthenticate())

    { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Login") .build() val biometricPrompt = BiometricPrompt(fragmentActivity, executor, authenticationCallback) biometricPrompt.authenticate(promptInfo, cryptoObject) } } BiometricPrompt.PromptInfo.Builder()
  37. androidx.biometric - API 14+ val biometricManager = BiometricManager.from(context) when (biometricManager.canAuthenticate())

    { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Login") .build() val biometricPrompt = BiometricPrompt(fragmentActivity, executor, authenticationCallback) biometricPrompt.authenticate(promptInfo, cryptoObject) } } BiometricPrompt(fragmentActivity,
  38. androidx.biometric - API 14+ val biometricManager = BiometricManager.from(context) when (biometricManager.canAuthenticate())

    { !" Suppress biometric UI BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_HW_UNAVAILABLE ./ suppressBiometrics() !" ask user to Enroll BIOMETRIC_ERROR_NONE_ENROLLED ./ startActivity(Intent(ACTION_FINGERPRINT_ENROLL)) !" Use biometrics BIOMETRIC_SUCCESS ./ { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Login") .build() val biometricPrompt = BiometricPrompt(fragmentActivity, executor, authenticationCallback) biometricPrompt.authenticate(promptInfo, cryptoObject) } } biometricPrompt.authenticate(
  39. CryptoObject package android.hardware.fingerprint; public class FingerprintManager { public static final

    class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public Signature getSignature() {…} public Cipher getCipher() {…} public Mac getMac() {…} } } public static final class CryptoObject { public CryptoObject(@NonNull Signature signature) {…} public CryptoObject(@NonNull Cipher cipher) {…} public CryptoObject(@NonNull Mac mac) {…} public java.security.Signature getSignature() {…} public javax.crypto.Cipher getCipher() {…} public javax.crypto.Mac getMac() {…} }
  40. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey()
  41. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() "AndroidKeyStore"
  42. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() "BiometricKey"
  43. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() .setUserAuthenticationRequired(true)
  44. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() .setInvalidatedByBiometricEnrollment(true)
  45. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() .generateKey()
  46. KeyGenParameterSpec val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init( Builder("BiometricKey", KeyProperties.PURPOSE_ENCRYPT or

    KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) !" API 24+ .build()) keyGenerator.generateKey() .generateKey()
  47. CryptoObject val keyStore: KeyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) 
 val key

    = keyStore.getKey("BiometricKey", null) as SecretKey val cipher: Cipher = Cipher.getInstance("AES/GCM/NoPadding") cipher.init(Cipher.DECRYPT_MODE, key) 
 val cryptoObject = BiometricPrompt.CryptoObject(cipher) "AndroidKeyStore"
  48. CryptoObject val keyStore: KeyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) 
 val key

    = keyStore.getKey("BiometricKey", null) as SecretKey val cipher: Cipher = Cipher.getInstance("AES/GCM/NoPadding") cipher.init(Cipher.DECRYPT_MODE, key) 
 val cryptoObject = BiometricPrompt.CryptoObject(cipher) "BiometricKey"
  49. CryptoObject val keyStore: KeyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) 
 val key

    = keyStore.getKey("BiometricKey", null) as SecretKey val cipher: Cipher = Cipher.getInstance("AES/GCM/NoPadding") cipher.init(Cipher.DECRYPT_MODE, key) 
 val cryptoObject = BiometricPrompt.CryptoObject(cipher) key key cipher cipher cryptoObject
  50. DOCS • Authenticating to remote servers using the Fingerprint API

    • https://android-developers.googleblog.com/2015/10/new-in-android-samples-authenticating.html • FingerprintManager Sample: • https://github.com/android/security-samples/tree/master/FingerprintDialogKotlin • Warning, always use CryptoObject, despite the example in this doc -> • https://developer.android.com/training/sign-in/biometric-auth • BiometricPrompt Sample: • https://android.googlesource.com/platform/frameworks/support/+/refs/ heads/androidx-master-dev/samples/BiometricDemos/
  51. BIOMETRIC AUTH IMPORTANT TAKE AWAYS • Use androidx.biometric • Always

    use CryptoObject • Consult with InfoSec Professionals
  52. Code samples are 
 Copyright The Android Open Source Project

    And Licensed under the Apache License, Version 2.0