I am using biometric authentication dialog but my cryptoObject is always null. I have a fragment but I also tried directly from the activity.
Here is my code,
private Handler biometricPromptHandler = new Handler();
private Executor executor = command -> biometricPromptHandler.post(command);
private void showBiometricPrompt( String title, String description,
BiometricsCompatCallback compatCallback) {
BiometricPrompt.PromptInfo promptInfo =
new BiometricPrompt.PromptInfo.Builder()
.setTitle(title)
.setSubtitle(description)
.setNegativeButtonText("Cancel")
.build();
BiometricPrompt biometricPrompt = new BiometricPrompt((FragmentActivity) context,
executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode,
@NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
compatCallback.onAuthenticationError(errorCode, errString);
Log.d("onAuthenticationError", ": ");
}
@Override
public void onAuthenticationSucceeded(
@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.d("result", ": "+(result.getCryptoObject()));
BiometricPrompt.CryptoObject authenticatedCryptoObject =
result.getCryptoObject();
Log.d("onAuthentionSucceeded", ": "+(authenticatedCryptoObject==null));
if (authenticatedCryptoObject != null) {
cipher = authenticatedCryptoObject.getCipher();
Log.d("onAuthentionSucceeded", ": ");
compatCallback.onAuthenticationSuccessful(cipher);
}else {
Log.d("cipher", "onAuthenticationSucceeded: ");
}
}
@Override
public void onAuthenticationFailed() {
Log.d("onAuthenticationFailed", ": ");
super.onAuthenticationFailed();
compatCallback.onAuthenticationFailed();
}
});
biometricPrompt.authenticate(promptInfo);
}
Anybody knows what I am doing wrong?
CryptoObjects are used to unlock auth-per-use keys via BiometricPrompt#authenticate(CryptoObject, CancellationSignal, Executor, AuthenticationCallback) , whereas time-based keys are unlocked for their specified duration any time the user authenticates with the specified authenticators (e.g. unlocking keyguard).
BiometricPrompt.Builder. A builder that collects arguments to be shown on the system-provided biometric dialog. class. BiometricPrompt.CryptoObject. A wrapper class for the cryptographic operations supported by BiometricPrompt.
You need to provide a Cipher in the second parameter of the authenticate
method or it will always return null
.
Use
authenticate(PromptInfo info, CryptoObject crypto)
instead of
authenticate(PromptInfo info)
Take a look to this tutorial and the sample project in this repository. You can use something like this:
BiometricPrompt.CryptoObject cryptoObject = new BiometricPrompt.CryptoObject(getEncryptCipher(createKey()));
biometricPrompt.authenticate(promptInfo, cryptoObject);
Using (depending on the ciphering you want):
private SecretKey createKey() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
String algorithm = KeyProperties.KEY_ALGORITHM_AES;
String provider = "AndroidKeyStore";
KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm, provider);
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder("MY_KEY", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
.build();
keyGenerator.init(keyGenParameterSpec);
return keyGenerator.generateKey();
}
private Cipher getEncryptCipher(Key key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
String algorithm = KeyProperties.KEY_ALGORITHM_AES;
String blockMode = KeyProperties.BLOCK_MODE_CBC;
String padding = KeyProperties.ENCRYPTION_PADDING_PKCS7;
Cipher cipher = Cipher.getInstance(algorithm+"/"+blockMode+"/"+padding);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With