AndroidKeyStore getEntry 在某个点之后始终失败

标签 android security encryption keystore android-keystore

我正在使用AndroidKeyStore生成RSA key 对,用于加密/解密内部数据。

执行此操作的代码如下 - 它尝试检索现有的 RSA key 对(通过别名)。如果不存在,那么它会尝试生成一个新的。 代码如下 -

private void initializePublicPrivateKeys(){
    try
    {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(APP_RSA_KEY_PAIR_SECRET_ALIAS, null);
        _app_privateRSAKey = entry.getPrivateKey();
        _app_publicRSAKey = entry.getCertificate().getPublicKey();
    }
    catch(Exception e){

    }
}

private void initializeRSAKeyPairs() {

    initializePublicPrivateKeys();
    boolean isKeyNotGenerated = _app_privateRSAKey == null || _app_publicRSAKey == null;

    if(isKeyNotGenerated)
    {
        //Check here, if we already stored some data with previous RSA key pair - if a entry is present in SharedPreference then that would mean we had previously generated a RSA key pair and the entry is in-turn encrypted by this key pair.

        generateAppRSAPublicPrivateKeys();
        initializePublicPrivateKeys();// initialize it again , since we have new keys generated.
    }
}

@TargetApi(18)
private void generateAppRSAPublicPrivateKeys(){
    Calendar cal = Calendar.getInstance();
    Date now = cal.getTime();
    // the certificate created would be valid for 25 years. This is just a random value.
    cal.add(Calendar.YEAR, 25);
    Date end = cal.getTime();

    try{
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        Context appContext = getApplicationContext();


        KeyPairGeneratorSpec.Builder keyPairGeneratorBuilder =
                new KeyPairGeneratorSpec.Builder(appContext)
                        .setAlias("myrsaalias")
                        .setStartDate(now)
                        .setEndDate(end)
                        .setSerialNumber(BigInteger.valueOf(1))
                        .setSubject(new X500Principal(String.format("CN=%s, OU=%s", "myrsaalias",
                                appContext.getApplicationInfo().packageName)));

        if(Build.VERSION.SDK_INT >= 19){
            keyPairGeneratorBuilder.setKeySize(2048); 
        }

        generator.initialize(keyPairGeneratorBuilder.build());
        generator.generateKeyPair();
    }
    catch(Exception e){
        e.printStackTrace();
        throw new IllegalArgumentException("Failed to generate RSA Public Private Key pair");
    }
}

这段代码工作正常。生成 key 对后,我使用它们来加密/解密数据(将此数据存储在共享首选项中),但是在某个时间点(在某些应用程序重新启动后)之后,initializePublicPrivateKeys 函数无法检索 key 对。(在这一点之后持续失败) 因此,以加密形式存储在共享首选项中的任何数据都会丢失,因为我根本没有相应的公钥来解密它。 (如果我生成一个新的,我想,这会有所不同,并且当我解密数据时会返回错误的结果)

我想知道在什么情况下这个initializePublicPrivateKeys函数会失败?

PS:目前,我无法捕获异常详细信息,因为问题发生在我无权访问的某些客户设备上,我需要自己找出问题的根源。 此外,在此期间设备密码或 PIN 码未更改(我与客户确认了这一点)

提前致谢,

最佳答案

是否有可能用户将屏幕锁定类型更改为不安全的方法(例如 None 或 Swipe),从而触发 AndroidKeyStore 中的所有 key 被删除?也许用户在设置中添加或删除了指纹? AndroidKeyStore 中的 key 无效是此博客文章中讨论的已知问题(功能):https://doridori.github.io/android-security-the-forgetful-keystore/

这里还提到:https://code.google.com/p/android/issues/detail?id=61989

如果您没有严格的安全要求,并且希望即使用户没有屏幕锁定,您的应用也能运行,那么也许只需使用存储在数据区域的 keystore 文件中的 key 对,并跳过 AndroidKeyStore.

关于AndroidKeyStore getEntry 在某个点之后始终失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30851985/

相关文章:

java - 不知道如何解释 GTFS 实时数据

android - 在 Android 中实现自定义后退导航

security - 在 symfony 身份验证中反序列化用户数据时出错

linux - 64位系统格式化字符串漏洞利用

c - SHA1 消息摘要到纯文本

android - 在AndEngine中修改贴图像素

android - 录制视频时保持预览回调?

security - 最佳密码盐长度

ios - CoreData加密提交到应用商店时是否需要任何类型的额外文件

ios - 如何使用 Bouncy CaSTLe 读取 App Store In App Purchase 收据? (PKCS7)