【问题标题】:Cannot generate key in Android keystore无法在 Android 密钥库中生成密钥
【发布时间】:2019-09-12 18:25:58
【问题描述】:

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

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();
}

有谁知道如何:

  • 以设备管理员身份锁定密钥库?
  • 密钥库被设备管理员锁定后解锁?
  • 或者以其他方式重现此问题?

【问题讨论】:

  • 显示如何创建密钥库的代码。
  • 你找到解决办法了吗?

标签: java android security keystore android-keystore


【解决方案1】:

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 不仅可以在 ICS 之前的设备上显示为已锁定。锁定KeyStore 的最简单方法是:

  1. 通过设置 KeyGuard(屏幕锁定上的图案、pin 或密码)来初始化 KeyStore
  2. 添加密钥或存储在 KeyStore 中的任何内容
  3. 转到设置 > 安全并将屏幕锁定更改为“不安全”的内容,例如幻灯片。
  4. 重启您的设备。

设备启动后,KeyStore 将被锁定。 com.android.credentials.UNLOCK intent 将启动 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 Initializing keystore without password

【讨论】:

  • 感谢您的回答贾米尔。但是,鉴于 KeyStore 条目不是使用密码创建的(请参阅问题中的 KeyPairGenerator. generateKeyPair() 方法调用),我看不出如何使用密码调用 KeyStore.getEntry(...) 方法。请解释一下。
  • 这个答案是从另一个答案stackoverflow.com/a/25951533/4473512复制而来的。一种诚实的方法应该是链接该答案以归功于作者。
  • @Manzotin 我不这么认为。相同的答案,但不同的方式。顺便说一句,我添加了链接。谢谢。
猜你喜欢
  • 2015-09-13
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多