在Android密钥库中无法生成密钥

22

我们目前遇到一个问题,即有时当用户安装我们的应用程序时,该应用程序会尝试访问并在密钥库中生成一个密钥,但是密钥库会抛出以下异常:

Caused by: 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)

我们认为这与手机的解锁模式无法解锁密钥库,和/或设备管理员锁定了密钥库有关。

以下是创建密钥库和生成密钥的方法:

public SecretKeyWrapper(Context context, String alias) throws GeneralSecurityException, IOException {
    mCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);

    if (!keyStore.containsAlias(alias)) {
        generateKeyPair(context, alias);
    }

    final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null);
    mPair = new KeyPair(entry.getCertificate().getPublicKey(), entry.getPrivateKey());
}

private static void generateKeyPair(Context context, String alias) throws GeneralSecurityException {
    final Calendar start = new GregorianCalendar();
    final Calendar end = new GregorianCalendar();
    end.add(Calendar.YEAR, 100);

    final KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
            .setAlias(alias)
            .setSubject(new X500Principal("CN=" + alias))
            .setSerialNumber(BigInteger.ONE)
            .setStartDate(start.getTime())
            .setEndDate(end.getTime())
            .build();

    final KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
    gen.initialize(spec);
    gen.generateKeyPair();
}

有人知道如何:

  • 将密钥库作为设备管理员锁定吗?
  • 当密钥库被设备管理员锁定时,如何解锁?
  • 或以其他方式重现此问题吗?

展示你创建Keystore的代码。 - Jorgesys
1
你找到解决方案了吗? - Nickolai Astashonok
1个回答

11

Caused by: java.lang.IllegalStateException: could not generate key in keystore

希望以下代码可以解决第一个异常:

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);

ks.getEntry(alias, new KeyStore.PasswordProtection(password))

如果设备管理员已将密钥库锁定,请解锁它:

KeyStore 不仅在早期版本的 Android(ICS 之前)上可能会被锁定。 锁定 KeyStore 最简单的方法是:

  1. 通过设置 KeyGuard(屏幕锁上的图案、密码或 PIN 码)初始化 KeyStore
  2. 添加密钥或其他存储在 KeyStore 中的内容
  3. 进入“设置” > “安全性”并将“屏幕锁定”更改为某些“不安全”的选项,例如“滑动”。
  4. 重新启动您的设备。

设备启动后,KeyStore 将被锁定。 com.android.credentials.UNLOCK 意图将启动 com.android.settings.CredentialStorage 活动,这将显示 UnlockDialog 并提示输入密码。

 * KeyStore: LOCKED
 * KeyGuard: OFF/ON
 * Action:   old unlock dialog
 * Notes:    assume old password, need to use it to unlock.
 *           if unlock, ensure key guard before install.
 *           if reset, treat as UNINITALIZED/OFF
你可以生成一个主密钥并将其存储为私有文件,其他应用程序将无法读取它,因此在非root设备上使用这种方法是可行的。这是Android开发者博客所推荐的方法:http://android-developers.blogspot.jp/2013/02/using-cryptography-to-store-credentials.html
相同问题的答案: Android android.credentials.UNLOCK 初始化密钥库而不需要密码

1
谢谢您的回答Jamil。然而,我看不出使用密码调用KeyStore.getEntry(...)方法有意义,因为密钥库条目并没有使用密码创建(请参见问题中的KeyPairGenerator.generateKeyPair()方法调用)。请解释一下。 - Adil Hussain
这个答案是从另一个答案 https://dev59.com/ln7aa4cB1Zd3GeqPlAuS#25951533 复制过来的。诚实的做法应该是链接到那个答案并给予作者以功劳。 - Manzotin
@Manzotin 我不这么认为。同样的答案,但是不同的方式。顺便说一下,我添加了链接。谢谢。 - Jamil Hasnine Tamim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接