BiometricPrompt.AuthenticationResult 中的 CryptoObject 始终为 null
The CryptoObject in BiometricPrompt.AuthenticationResult is always null
我正在使用生物识别身份验证对话框,但我的 cryptoObject 始终为空。
我有一个片段,但我也直接从 activity 尝试过。
这是我的代码,
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);
}
有人知道我做错了什么吗?
您需要在 authenticate
方法的第二个参数中提供密码,否则它将始终 return null
.
使用
authenticate(PromptInfo info, CryptoObject crypto)
而不是
authenticate(PromptInfo info)
看看this tutorial and the sample project in this repository。你可以使用这样的东西:
BiometricPrompt.CryptoObject cryptoObject = new BiometricPrompt.CryptoObject(getEncryptCipher(createKey()));
biometricPrompt.authenticate(promptInfo, cryptoObject);
使用(取决于你想要的加密):
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;
}
要从 AuthenticationResult
获取 CryptoObject
,您必须在调用 authenticate()
时首先传入 CryptoObject
,如下所示:
// this example uses a Cipher but your code can use signature or mac
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
如果您在调用 authenticate()
时没有传递 CryptoObject,则 API 没有 return 给您。
查看 this blog post。
我正在使用生物识别身份验证对话框,但我的 cryptoObject 始终为空。 我有一个片段,但我也直接从 activity 尝试过。
这是我的代码,
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);
}
有人知道我做错了什么吗?
您需要在 authenticate
方法的第二个参数中提供密码,否则它将始终 return null
.
使用
authenticate(PromptInfo info, CryptoObject crypto)
而不是
authenticate(PromptInfo info)
看看this tutorial and the sample project in this repository。你可以使用这样的东西:
BiometricPrompt.CryptoObject cryptoObject = new BiometricPrompt.CryptoObject(getEncryptCipher(createKey()));
biometricPrompt.authenticate(promptInfo, cryptoObject);
使用(取决于你想要的加密):
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;
}
要从 AuthenticationResult
获取 CryptoObject
,您必须在调用 authenticate()
时首先传入 CryptoObject
,如下所示:
// this example uses a Cipher but your code can use signature or mac
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
如果您在调用 authenticate()
时没有传递 CryptoObject,则 API 没有 return 给您。
查看 this blog post。