Я пишу знаковую функцию Android, которая принимает открытый текст byte [] и возвращает подпись byte []. Он использует частный защищенный элемент от телефона Android для подписи, что требует аутентификации Biometri c (biometricPrompt.authentication).
Я пробовал много способов сделать это, но каждый раз это терпит неудачу. В приведенном ниже коде не отображается приглашение Biometri c во время выполнения, оно просто зависает на главном экране из-за biometricPrompt.wait (). Я много искал решение, но не нашел. Пожалуйста помоги. :)
private MainActivityTest mainAct = null;
private byte[] sig = null;
public AndroidSecureElement(MainActivity mainAct){
this.mainAct = mainAct;
}
public byte[] signSE(final String alias, final byte[] plaintext) throws Exception {
final Executor executor;
final BiometricPrompt biometricPrompt;
final BiometricPrompt.PromptInfo promptInfo;
KeyStore keyStore = null;
final Signature s;
PrivateKey privKey = null;
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
privKey = (PrivateKey)keyStore.getKey(alias, null);
if(privKey.getAlgorithm().equalsIgnoreCase("RSA")){
s = Signature.getInstance("SHA256withRSA");
}
else if(privKey.getAlgorithm().equalsIgnoreCase("EC")){
s = Signature.getInstance("SHA256withECDSA");
}
else{
throw new Exception("Sign Failed: Unknown Algorithm found: "+privKey.getAlgorithm());
}
privKey = (PrivateKey)keyStore.getKey(alias, null);
s.initSign(privKey);
executor = ContextCompat.getMainExecutor(mainAct);
biometricPrompt = new BiometricPrompt(mainAct,
executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode,
@NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Toast.makeText(mainAct.getApplicationContext(),
"Authentication error: " + errString, Toast.LENGTH_SHORT)
.show();
this.notify();
}
@Override
public void onAuthenticationSucceeded(
@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Toast.makeText(mainAct.getApplicationContext(),
"Authentication succeeded!", Toast.LENGTH_SHORT).show();
try {
Signature s = result.getCryptoObject().getSignature();
s.update(plaintext);
sig = s.sign();
} catch (Exception e) {
Toast.makeText(mainAct.getApplicationContext(),
"Sign failed!", Toast.LENGTH_SHORT).show();
}
finally{
this.notify();
}
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(mainAct.getApplicationContext(), "Authentication failed",
Toast.LENGTH_SHORT)
.show();
this.notify();
}
});
promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for Secure Element access")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Cancel")
.setConfirmationRequired(true)
.build()
;
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(s));
synchronized (biometricPrompt) {
biometricPrompt.wait();
}
return sig;
}