【发布时间】:2016-04-21 10:16:43
【问题描述】:
我正在尝试将 android Fingerprint 实现到示例应用程序中。 使用的密码未被识别为有效 - 但我不知道为什么,因为基于 android 文档,应该支持它。
密码建立在:
return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_RSA + "/" +KeyProperties.BLOCK_MODE_ECB + "/" + KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
这个密码列在官方docs。
后面用到的keyGenerator和keyFactory的生成方式如下。
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.
我还使用该密码初始化密钥生成器:
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();
我也在加密过程中添加了公钥,而公钥是这样生成的:
private PublicKey getPublicKey() throws GeneralSecurityException {
PublicKey publicKey = keyStore.getCertificate(keyAlias).getPublicKey();
KeySpec spec = new X509EncodedKeySpec(publicKey.getEncoded());
return keyFactory.generatePublic(spec);
}
编辑:添加了私钥部分:
PrivateKey getPrivateKey() throws GeneralSecurityException {
return (PrivateKey) keyStore.getKey(keyAlias, null);
}
实际的指纹处理如下:
Cipher cipher = createCipher();
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), cancellationSignal,
0, new FingerprintManager.AuthenticationCallback() {/* cutted */ }, null);
解密:
cipher = createCipher();
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), cancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {}, null);
结果如下:
进程:com.example.android.fingerprintdialog,PID:16254 java.lang.IllegalArgumentException:加密原语不受 AndroidKeyStore 提供程序支持:javax.crypto.Cipher@2419dda,spi:com.android.org.conscrypt.OpenSSLCipherRSA$PKCS1@4a4d20b
完整的堆栈跟踪:
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)
【问题讨论】:
-
你能把你的电话显示给
KeyPairGenerator.getInstance吗? -
您的示例说您使用 getPrivateKey 初始化 Cipher,但它没有提供 getPrivateKey 的代码。请提供 getPrivateKey 的代码。
-
谢谢迈克尔和亚历克斯 - 我想我添加了必要的细节。如果需要更多详细信息以及是否应该将课程上传到 github 或 gist,请告诉我。
-
你能找到解决这个问题的方法吗?
-
我能够在 Android M 和 RSA 上使用它,我认为您不需要使用 KeyFactory。查看此代码并对其进行调整以使用 RSA blog.stylingandroid.com/user-authentication-part-1
标签: android android-keystore android-security android-fingerprint-api