【问题标题】:Android KeyStore operation failed: Unsupported DigestAndroid KeyStore 操作失败:不支持的摘要
【发布时间】:2018-11-21 08:42:34
【问题描述】:

我在大约 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)

这是我们创建密钥对的方式:

@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);
        }
    }

在解密时启动错误,就在执行 cipher.init 时。

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

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

【问题讨论】:

    标签: android encryption keystore


    【解决方案1】:

    我和你有同样的经历。根据我的研究,我认为原因是用户可能会进行不满意的固件更新! (例如,Nexus 6P 中的 android P (9),Nexus 6p 的最终更新是 8.0.1。)您必须查看该用户设备是否支持正确的操作系统版本。稍后告诉我您的支票。

    【讨论】:

    • 很好,我同意
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2022-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多