I'm trying to implement android Fingerprint into a sample application. The used cipher is not recogniced as valid - but I dont know why, since based on the android docs, it should be supported.
The cipher is built on:
return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_RSA + "/" +KeyProperties.BLOCK_MODE_ECB + "/" + KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
This cipher listed in the official docs.
The keyGenerator and keyFactory which is used later on is generated as follows.
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null); // Ensure the key store can be loaded before continuing.
keyGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
keyFactory = KeyFactory.getInstance("RSA");
createCipher(); // If this doesn't throw, the cipher we need is available.
I also initialize the keygenerator with that cipher:
keyGenerator.initialize(new KeyGenParameterSpec.Builder(keyAlias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) //
.setBlockModes(KeyProperties.BLOCK_MODE_ECB) //
.setUserAuthenticationRequired(true) //
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) //
.build());
keyGenerator.generateKeyPair();
I also add the public key to the encryption process, while the public key is generated this way:
private PublicKey getPublicKey() throws GeneralSecurityException {
PublicKey publicKey = keyStore.getCertificate(keyAlias).getPublicKey();
KeySpec spec = new X509EncodedKeySpec(publicKey.getEncoded());
return keyFactory.generatePublic(spec);
}
edit: added the part of the private key:
PrivateKey getPrivateKey() throws GeneralSecurityException {
return (PrivateKey) keyStore.getKey(keyAlias, null);
}
the actual fingerprint handling is then as follows:
Cipher cipher = createCipher();
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), cancellationSignal,
0, new FingerprintManager.AuthenticationCallback() {/* cutted */ }, null);
the decryption:
cipher = createCipher();
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), cancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {}, null);
Resulting in the following:
Process: com.example.android.fingerprintdialog, PID: 16254 java.lang.IllegalArgumentException: Crypto primitive not backed by AndroidKeyStore provider: javax.crypto.Cipher@2419dda, spi: com.android.org.conscrypt.OpenSSLCipherRSA$PKCS1@4a4d20b
full stacktrace:
04-21 11:48:00.031 16254-16254/com.example.android.fingerprintdialog E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.fingerprintdialog, PID: 16254
java.lang.IllegalArgumentException: Crypto primitive not backed by AndroidKeyStore provider: javax.crypto.Cipher@2419dda, spi: com.android.org.conscrypt.OpenSSLCipherRSA$PKCS1@4a4d20b
at android.security.keystore.AndroidKeyStoreProvider.getKeyStoreOperationHandle(AndroidKeyStoreProvider.java:160)
at android.hardware.fingerprint.FingerprintManager$CryptoObject.getOpId(FingerprintManager.java:248)
at android.hardware.fingerprint.FingerprintManager.authenticate(FingerprintManager.java:468)
at android.hardware.fingerprint.FingerprintManager.authenticate(FingerprintManager.java:429)
at com.example.android.fingerprintdialog.MainActivity.tryToEncrypt(MainActivity.java:212)
at com.example.android.fingerprintdialog.MainActivity.access$000(MainActivity.java:61)