我使用KeyPermanentlyInvalidatedException来检测添加了新指纹。但它并没有抛出KeyPermanentlyInvalidatedException。
我尝试了这些步骤:
我也从stackoverflow中找到了这个link,但它对我没有帮助。
来自文件:
一旦禁用安全锁定屏幕(重新配置为无,刷卡或其他未对用户进行身份验证的模式)或强制重置安全锁定屏幕(例如,由设备管理员),密钥将变为不可逆转无效。此外,如果密钥要求每次使用密钥时都进行用户身份验证,则一旦注册新指纹或一旦不再注册指纹,它也会不可逆转地无效,除非在注册后使用setInvalidatedByBiometricEnrollment(boolean)来允许有效性。尝试使用此类密钥初始化加密操作将导致KeyPermanentlyInvalidatedException。
这是我的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authenticate);
mButtonTest = findViewById(R.id.button_test);
mButtonTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
buttonTestOnClick();
}
});
boolean isFirstTime = PreferenceManager.getInstances().getFirstTime();
PreferenceManager.getInstances().setFirstTime(false);
if (isFirstTime) {
createKeyPair();
}
}
private void buttonTestOnClick() {
boolean result = initSignature();
Log.e("iii", "Create signature result: " + result);
boolean isFirstTime = PreferenceManager.getInstances().getFirstTime();
if (result) {
if (isFirstTime) {
enroll();
}
startListening();
}
}
/**
* Generates an asymmetric key pair in the Android Keystore. Every use of the private key must
* be authorized by the user authenticating with fingerprint. Public key use is unrestricted.
*/
public void createKeyPair() {
try {
mKeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("Failed to get an instance of KeyPairGenerator", e);
}
// The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
// for your flow. Use of keys is necessary if you need to know if the set of
// enrolled fingerprints has changed.
try {
// Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder
mKeyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
// Require the user to authenticate with a fingerprint to authorize
// every use of the private key
.setUserAuthenticationRequired(true)
.build());
mKeyPairGenerator.generateKeyPair();
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
}
/**
* Initialize the {@link Signature} instance with the created key in the
* {@link #createKeyPair()} method.
*
* @return {@code true} if initialization is successful, {@code false} if the lock screen has
* been disabled or reset after the key was generated, or if a fingerprint got enrolled after
* the key was generated.
*/
private boolean initSignature() {
// Create keystore
try {
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (KeyStoreException e) {
throw new RuntimeException("Failed to get an instance of KeyStore", e);
}
// Create signature
try {
mSignature = Signature.getInstance("SHA256withECDSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Failed to get an instance of Signature", e);
}
try {
mKeyStore.load(null);
PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_NAME, null);
mSignature.initSign(key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
private void enroll() {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
PublicKey publicKey = keyStore.getCertificate(AuthenticateActivity.KEY_NAME).getPublicKey();
// Provide the public key to the backend. In most cases, the key needs to be transmitted
// to the backend over the network, for which Key.getEncoded provides a suitable wire
// format (X.509 DER-encoded). The backend can then create a PublicKey instance from the
// X.509 encoded form using KeyFactory.generatePublic. This conversion is also currently
// needed on API Level 23 (Android M) due to a platform bug which prevents the use of
// Android Keystore public keys when their private keys require user authentication.
// This conversion creates a new public key which is not backed by Android Keystore and
// thus is not affected by the bug.
KeyFactory factory = KeyFactory.getInstance(publicKey.getAlgorithm());
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey.getEncoded());
PublicKey verificationKey = factory.generatePublic(spec);
//mStoreBackend.enroll("user", "password", verificationKey);
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException |
IOException | InvalidKeySpecException e) {
e.printStackTrace();
}
}
但 initSignature()函数allways返回true。