Android Keystore getEntry()和generateKeyPair()有时会抛出异常

Kak*_*udu 19 java security android

我的Android应用程序需要加密文件,以便以后可以解密和读取.除了应用程序,甚至用户之外,其他任何人都无法解密.

以下是我如何进行加密和解密.这在大多数情况下都有效,但有些用户有时会失败.它不是特定的手机(Nexus7,三星,摩托罗拉,HTC - 所有类型都报告此问题),但并非所有用户都遇到它.偶尔只有一些用户.

这是相关代码:

encrypt() {
   KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
   final KeyStore.PrivateKeyEntry entry;
   if (!ks.containsAlias(CERT_ALIAS)) {
       Calendar cal = Calendar.getInstance();
       Date now = cal.getTime();
       cal.add(Calendar.YEAR, 50);
       Date end = cal.getTime();
       KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
       kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext())
              .setAlias(CERT_ALIAS)
              .setStartDate(now)
              .setEndDate(end)
              .setSerialNumber(BigInteger.valueOf(1))
              .setSubject(new X500Principal("CN=" + CERT_ALIAS))
              .build());
       KeyPair kp = kpg.generateKeyPair();
   }
   entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
                     CERT_ALIAS, null);
   pub = entry.getCertificate().getPublicKey();
   // use the pub key to encrypt
}
decrypt() {
    KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
    ks.load(null);

    final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
            CERT_ALIAS, null);
    PrivateKey key1 = entry.getPrivateKey();
    // use the private key decrypt
}
Run Code Online (Sandbox Code Playgroud)

此代码有时会抛出

java.lang.RuntimeException: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
at com.android.org.conscrypt.NativeCrypto.ENGINE_load_private_key(Native Method)
at com.android.org.conscrypt.OpenSSLEngine.getPrivateKeyById(OpenSSLEngine.java:66)
at android.security.AndroidKeyStore.engineGetKey(AndroidKeyStore.java:86)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372)
at java.security.KeyStore.getEntry(KeyStore.java:644)
Run Code Online (Sandbox Code Playgroud)

所以我修改了encrypt()以首先尝试获取条目,如果它引发异常,则生成新的密钥对.

final KeyStore.PrivateKeyEntry entry = null;
if (ks.containsAlias(CERT_ALIAS)) {
    try {
        entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
                      CERT_ALIAS, null);
    } catch (Exception e) {
    }
}
if (entry == null) {
    //generate new key pair
}
Run Code Online (Sandbox Code Playgroud)

但即使这种情况有时会失败,但有以下例外情况.

java.lang.IllegalStateException: could not generate key in keystore
at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100)
at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275)
Run Code Online (Sandbox Code Playgroud)
  1. 我究竟做错了什么?
  2. 我该如何解决/解决它?
  3. 这些异常是否表明文件被篡改?
  4. 对于屏幕锁定密码/ pin的用户,是否会发生这种情况?
  5. 在我生成新对之前,我应该删除该条目吗?(KeyStore.deleteEntry())

我发现在屏幕锁定密码/引脚更改后密钥库返回null.其他一些人似乎也遇到过这个问题(更改密码后KeyStore getEntry返回null)

小智 6

could not generate key in keystore用我的一个应用程序遇到了这个问题,在深入了解其中一个受影响的手机后,我发现有些设备设置了手机的解锁模式/通道/引脚与实际解锁密钥的密码不同存储.如果你想仔细检查这是你的问题,你可以使用这里的工作:http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html来了解实际情况私有系统api公共KeyPairGenerator对象正在调用并检查其上的返回码.我不确定谷歌为什么决定隐藏布尔值背后的返回码,但是你有它.

您可以通过调用手动触发密钥库的解锁,startActivity(new Intent("com.android.credentials.UNLOCK"));但这可能没有多大帮助.从我所看到的,如果手机处于这种状态,这是因为某些设备管理员应用程序在后台锁定了密钥库,因此它可以设置VPN或电子邮件凭据.这意味着用户实际上并不知道密码.我仍然在寻找一种解决方法(可能会发现设备管理员应用程序如何访问密钥库,以便我可以解锁它),但至少可以说是一个毛茸茸的问题.如果我在探索中发现更多内容,我会尝试更新此内容,希望这至少可以指出一些人正朝着正确的方向前进.