Android KeyStore操作失败:不支持摘要



我在使用我的大约1%的用户(在不同的API版本和设备型号中(的密钥库解密数据时出错。崩溃日志为:

Caused by java.lang.RuntimeException: java.security.InvalidKeyException: Keystore operation failed
at es.xxxx.yyyy.utils.KeyStoreHelperManager.decrypt(KeyStoreHelperManager.java:256)
at es.xxxx.yyyy.activities.MainActivity.checkKeyStoreCorrecto(MainActivity.java:308)
at es.xxxx.yyyy.activities.MainActivity.configurarLayout(MainActivity.java:294)
at es.xxxx.yyyy.activities.MainActivity.onCreate(MainActivity.java:84)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2894)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by java.security.InvalidKeyException: Keystore operation failed
at android.security.KeyStore.getInvalidKeyException(KeyStore.java:901)
at android.security.KeyStore.getInvalidKeyException(KeyStore.java:926)
at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1143)
at javax.crypto.Cipher.init(Cipher.java:1084)
at es.xxxx.yyyy.utils.KeyStoreHelperManager.decrypt(KeyStoreHelperManager.java:251)
at es.xxxx.yyyy.activities.MainActivity.checkKeyStoreCorrecto(MainActivity.java:308)
at es.xxxx.yyyy.activities.MainActivity.configurarLayout(MainActivity.java:294)
at es.xxxx.yyyy.activities.MainActivity.onCreate(MainActivity.java:84)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2894)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by android.security.KeyStoreException: Unsupported digest
at android.security.KeyStore.getKeyStoreException(KeyStore.java:839)
at android.security.KeyStore.getInvalidKeyException(KeyStore.java:926)
at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
at javax.crypto.Cipher.init(Cipher.java:1143)
at javax.crypto.Cipher.init(Cipher.java:1084)
at es.xxxx.yyyy.utils.KeyStoreHelperManager.decrypt(KeyStoreHelperManager.java:251)
at es.xxxx.yyyy.activities.MainActivity.checkKeyStoreCorrecto(MainActivity.java:308)
at es.xxxx.yyyy.activities.MainActivity.configurarLayout(MainActivity.java:294)
at es.xxxx.yyyy.activities.MainActivity.onCreate(MainActivity.java:84)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2894)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
#0. Crashed: main
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2914)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

这是我们创建KeyPair:的方式

@TargetApi(Build.VERSION_CODES.M)
static void createKeysM(String alias, boolean requireAuth) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(1024, F4))
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setRandomizedEncryptionRequired(false)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setDigests(KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512)
// Only permit the private key to be used if the user authenticated
// within the last five minutes.
.setUserAuthenticationRequired(requireAuth)
.build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
Log.d(TAG, "Public Key is: " + keyPair.getPublic().toString());
} catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
}

这是我们用来加密数据的方法:

public static String encrypt(String alias, String plaintext) {
try {
KeyStore ks = KeyStore
.getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
ks.load(null);

//PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", null);
PublicKey publicKey = ks.getCertificate(alias).getPublicKey();

//PublicKey publicKey = getPrivateKeyEntry(alias).getCertificate().getPublicKey();
Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeToString(cipher.doFinal(plaintext.getBytes()), Base64.NO_WRAP);
} catch (NullPointerException  ex){
Logs.logException(ex);
throw ex;
}
catch (Exception e) {
Logs.logException(e);
throw new RuntimeException(e);
}
}

这就是解密数据的方法:

public static String decrypt(String alias, String ciphertext) throws IllegalBlockSizeException {
try {
KeyStore ks = KeyStore
.getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
ks.load(null);

PrivateKey privateKey = (PrivateKey) ks.getKey(alias, null);

//PrivateKey privateKey = getPrivateKeyEntry(alias).getPrivateKey();
Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(Base64.decode(ciphertext, Base64.NO_WRAP)));
}catch (IllegalBlockSizeException ex){
throw ex;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

该错误是在解密时启动的,只是在进行加密.init时。

我们的密码是这样创建的:

private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
return Cipher.getInstance(
String.format("%s/%s/%s",
"RSA",
"NoPadding",
"BLOCKING_MODE"));
}

我和你有过同样的经历。作为我的研究,我决定,原因是用户可能会做不费力的固件更新!(例如,android P(9(在Nexus 6P中,Nexus 6P的最终更新是8.0.1。(你必须看看用户设备是否支持正确的操作系统版本。请稍后通知我您的支票。

相关内容

最新更新