【问题标题】:android.security.KeyStoreException: Invalid key blobandroid.security.KeyStoreException:无效的密钥 blob
【发布时间】:2016-07-29 01:05:25
【问题描述】:

我无法从 Android 上的 KeyStore 获取(私有)密钥。主要出现问题 在三星设备(S6、S6 Edge)和 Android 6 上。

android.security.KeyStoreException:无效的密钥 blob

在调用下一行时抛出(其中别名是存储键的名称)。

KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);

KeyStore本身是通过

获取的
KeyStore.getInstance("AndroidKeyStore");

而key是通过以下方法生成的:

private static void createKey(String alias, String subject, KeyStore keyStore, BigInteger serialNumber, Date startDate, Date endDate, String algorithm, String keyStoreProvider, Context context)
            throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
    if (keyStore.containsAlias(alias)) {
        // Key already exists.
        return;
    }

    // Generate keys.
    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
            .setAlias(alias)
            .setSubject(new X500Principal(subject))
            .setSerialNumber(serialNumber)
            .setStartDate(startDate)
            .setEndDate(endDate)
            .build();

    KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm, keyStoreProvider);
    generator.initialize(spec);

    KeyPair keyPair = generator.generateKeyPair();
}

其中算法是“RSA”,keyStoreProvider 是“AndroidKeyStore”。

stacktrace的部分:

android.security.KeyStoreException: Invalid key blob
       at android.security.KeyStore.getKeyStoreException(KeyStore.java:939)
       at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:216)
       at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:252)
       at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(AndroidKeyStoreProvider.java:263)
       at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:93)
       at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372)
       at java.security.KeyStore.getEntry(KeyStore.java:645)

该异常导致抛出java.security.UnrecoverableKeyException: Failed to get information about private key

我无法找到有关“无效密钥 blob”的任何更详细信息, 只是消息本身在这里定义:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/security/keymaster/KeymasterDefs.java

【问题讨论】:

  • 这听起来像是这些设备上硬件支持的 keymaster(Android Keystore 的加密提供程序)的问题。在此异常之前的几秒钟内,系统日志中有什么有趣的东西吗?例如,任何提及“keymaster”、与键/blob 相关的错误、qseecom?
  • @AlexKlyubin 谢谢你的建议,我去看看。
  • @Ankis,我遇到了同样的问题。您已经找到解决方案了吗?
  • @DinoTw 还没有。我从 Crashlytics 获得了有关该问题的信息,在我设法测试的设备上,我还无法重现它。应该可以访问其他设备,因此希望会有一些进展。你碰巧知道如何一步一步地重现它吗?您是否注意到任何可能导致它的设备状态(屏幕锁定设置,...)?
  • 当我将操作系统从 Android 5 升级到 Android 6 时,我遇到了这个问题,我在这里发布了我的问题并讨论了我目前的解决方法,stackoverflow.com/q/36652675/691626。从 4 升级到 5 可以正常工作,我猜是因为 API 更改。

标签: android security android-keystore


【解决方案1】:

当用户尝试从LOCK/UNINITIALIZED 访问UNLOCK 时会出现此问题。默认情况下,它被定义为30 secs 用于计时。 这个问题是API相关的实现问题。

此错误是从InvalidKeyException 生成的。绕过这个异常,再次调用该方法,就可以摆脱这个错误了。

您必须从 catch 参数中删除 InvalidKeyException 类。这仍然允许您检查InvalidKeyException。检查后,您必须第二次尝试使用代码,以便问题不会显示在眼睛中,但进行 2 次检查可能会解决您的问题。代码如下。

try {
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore
            .getEntry("alias", null);

} catch (InvalidKeyException ex) {
    ex.printStackTrace();
    if (ex instanceof InvalidKeyException) { // bypass
                                                // InvalidKeyException
        // You can again call the method and make a counter for deadlock
        // situation or implement your own code according to your
        // situation
        if (retry) {
            keyStore.deleteEntry(keyName);
            return getCypher(keyName, false);
        } else {
            throw ex;
        }
    }
} catch (final Exception e) {
    e.printStackTrace();
    throw e;
}

您可以看到我的另一个answer,它一一描述了发生的情况 问题和解决方案。

来自@Ankis的更新:

当您通过将InvalidKeyException 更改为UnrecoverableKeyException 来解决问题时。因此,我已根据您的建议进行了更新,以便世界知道实际答案。感谢分享:)。

try {
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore
            .getEntry("alias", null);

} catch (UnrecoverableKeyException ex) {
    ex.printStackTrace();
        // You can again call the method and make a counter for deadlock
        // situation or implement your own code according to your
        // situation
        if (retry) {
            keyStore.deleteEntry(keyName);
            return getCypher(keyName, false);
        }
} catch (final Exception e) {
    e.printStackTrace();
    throw e;
}

【讨论】:

  • 抱歉反应迟了。我在您的链接问题中使用与海报类似的解决方案 - 捕获异常,确定原因是否与此特定情况匹配,然后尝试再次检索密钥。如果您更新您的答案代码(不需要实例检查,从 InvalidKeyException 更改为 UnrecoverableKeyException)我将接受答案。
  • @Ankis 我已经更新了答案。如果需要任何更改,请告知。我会更新的。
  • keyStore.deleteEntry(keyName) 调用的目的是什么?当然,如果您删除密钥并再次尝试获取它,它就不会再存在了吗??
  • @SkyWalker 密钥库文档中是否有支持您在此处建议的内容?
  • 删除条目如何解决问题?之后就无法解密用户的数据了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
  • 2017-12-02
  • 2023-03-20
  • 2021-03-01
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多