Android KeyStore - 密钥并不总是持久的

Posted

技术标签:

【中文标题】Android KeyStore - 密钥并不总是持久的【英文标题】:Android KeyStore - keys not always persisted 【发布时间】:2016-06-20 10:30:56 【问题描述】:

在我的应用程序中,我们使用 RSA 密钥,该应用程序在首次启动时生成(使用 android 密钥库)。由于未知原因,该应用未能从某些设备上的密钥库中检索到密钥。我检查了日志,但找不到此错误与特定操作系统版本或特定设备型号之间的关联。另外,我确定该应用程序仅在创建密钥后才尝试读取它。所以 - 我的问题是:据我所知,android 密钥库应该是持久的。什么会导致这样的错误?

下面是相关的代码示例。

密钥生成:

try 
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", keyStore.getProvider());

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
            KeyGenParameterSpec spec;
            spec = new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT| KeyProperties.PURPOSE_SIGN| KeyProperties.PURPOSE_VERIFY)
                    .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                    .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                    .setKeySize(2048)
                    .build();

            generator.initialize(spec);
         else 
            Calendar start = new GregorianCalendar();
            Calendar end = new GregorianCalendar();
            end.add(Calendar.YEAR, 500);

            KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                    .setAlias(alias)
                    .setSubject(new X500Principal("CN="+ subject))
                    .setSerialNumber(BigInteger.valueOf(new Random().nextInt(Integer.MAX_VALUE)))
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .setKeySize(2048)
                    .build();

            generator.initialize(spec);
        
        return generator.generateKeyPair();
     catch (Exception e) 
        logger.warn("Failed to create private key in store", e);
        return null;
    

使用以下代码初始化密钥库本身:

KeyStore androidKeyStore = KeyStore.getInstance("AndroidKeyStore");
            androidKeyStore.load(null);
            return androidKeyStore;

我们使用以下代码来检索密钥,错误是在某些设备上密钥库返回 null:

        try 
        Key key = keyStore.getKey(alias, null);

        if (key == null)
            logger.warn("Key not found in key store");
            return null;
        

        if (key instanceof PrivateKey) 
            // Get certificate of public key
            Certificate cert = keyStore.getCertificate(alias);

            // Get public key
            PublicKey publicKey = cert.getPublicKey();

            // Return a key pair
            return new KeyPair(publicKey, (PrivateKey) key);
         else 
            logger.warn("Key found, but not from current type. type found: " + key.getClass().getSimpleName());
        
        return null;
    catch (Exception e)
        logger.warn("Failed to get private key in store", e);
        return null;
    

谢谢, 奥马尔

【问题讨论】:

【参考方案1】:

以防万一有人遇到同样的问题: 我发现适用于 android 的 Azure Active Directory 库遭受类似的issue 的影响,并且通过阅读我看到它们链接到two issues 的代码类似于这个问题和我们遇到的另一个问题。因此,我打算使用基于 p12 文件的密钥库,存储在应用程序私有存储中。

【讨论】:

【参考方案2】:

您的密钥是在生成后立即丢失还是在一段时间后丢失?看看这个问题AndroidKeyStore getEntry is consistently failing after certain point 链接到这篇很棒的文章:http://doridori.github.io/android-security-the-forgetful-keystore/

这个故事的寓意是,如果您使用 AndroidKeyStore,请准备好在某些情况下丢失您的密钥!

【讨论】:

是的,我也想通了。这就是我停止使用 Android KeyStore 的原因。谢谢!

以上是关于Android KeyStore - 密钥并不总是持久的的主要内容,如果未能解决你的问题,请参考以下文章

Android密钥库系统KeyStore

Android Studio apk打包,keystore.jks文件生成,根据keystore密钥获取SHA1安全码

Android Keystore 对称-非对称加密

Android导出:如何创建.keystore文件?

Hbuilder打包时Android的keystore怎么生成

“.android”文件夹和“debug.keystore”文件丢失