I am trying to develop a function in my Android application that will alert me when a user changes the device fingerprint without having to call the device biometric prompt. I have attempted this using a biometric library in my code.
I only generated the secret key ,when I have open the app for the first time using below code:
if ( secretKey == null || secretKey.isDestroyed() ){
try {
Log.d("tt", "900000");
generateSecretKey(new KeyGenParameterSpec.Builder(
"KEY_NAME",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
// Invalidate the keys if the user has registered a new biometric
// credential, such as a new fingerprint. Can call this method only
// on Android 7.0 (API level 24) or higher. The variable
// "invalidatedByBiometricEnrollment" is true by default.
.setInvalidatedByBiometricEnrollment(true).setUnlockedDeviceRequired()
.build());
secretKey = getSecretKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
However, when I open the settings and change only the name of the fingerprint, it alerts me that the fingerprint has changed, even though I did not add a new fingerprint. It raised an IllegalBlockSizeException error as shown in the figure
IllegalBlockSizeException error
Tried this on a Galaxy S7 Android 8 , Can someone help me figure out how to detect actual changes to fingerprints?
private Boolean initCipher (Cipher cipher ){
try {
SecretKey finalSecretKey = getSecretKey();
cipher.init(Cipher.ENCRYPT_MODE, finalSecretKey);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
Log.e("invalidchanged","yesss");
Toast.makeText(getApplicationContext(),
"Biometric changed", Toast.LENGTH_SHORT).show();
return false;
} catch (InvalidKeyException e) {
return false;
//throw new RuntimeException(e);
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
return false;
}
private void isBiometricChanged(){
Cipher cipher = getCipher();
SecretKey finalSecretKey = null;
try {
finalSecretKey = getSecretKey();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException | IOException | NoSuchAlgorithmException | UnrecoverableKeyException e ) {
e.printStackTrace();
}
// BiometricPrompt.CryptoObject(cipher);
isBiometricChanged = !(initCipher(cipher));
if (finalSecretKey == null || finalSecretKey.isDestroyed()){
return;
}
if(finalSecretKey != null && !isBiometricChanged ){
try {
cipher.doFinal(
// plaintext-string text is whatever data the developer would like
// to encrypt. It happens to be plain-text in this example, but it
// can be anything
"plaintext-string".getBytes(Charset.defaultCharset()));
} catch (BadPaddingException e) {
Log.e("87777777777777777", "errr");
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
BiometricManager biometricManager = BiometricManager.from(this);
Log.e("999999999999999", "errr");
Log.e("ci:::", String.valueOf(cipher));
Log.e("ci1:::", String.valueOf(initCipher(cipher)));
Log.e("ci2:::", String.valueOf(finalSecretKey.toString()));
Log.e("ci3:::", String.valueOf(e));
Log.e("ci4:::", String.valueOf(isBiometricChanged));
Log.e("ci5:::", String.valueOf(finalSecretKey));
isBiometricChanged = true;
Toast.makeText(getApplicationContext(),
"changed ", Toast.LENGTH_SHORT).show();
e.printStackTrace();
// throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
}
}
}
private void generateSecretKey(KeyGenParameterSpec keyGenParameterSpec) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
private SecretKey getSecretKey() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
// Before the keystore can be accessed, it must be loaded.
keyStore.load(null);
return ((SecretKey)keyStore.getKey("KEY_NAME", null));
}