Chain is null when retrieving private key

I'm encrypting data in my app using a RSA keypair that I am storing in the Android keystore.

I've been seeing NullPointerExceptions in the Play Store, but I have not been able to reproduce them:

java.lang.NullPointerException: chain == null
    at java.security.KeyStore$PrivateKeyEntry.<init>(KeyStore.java:1205)
    at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:374)
    at java.security.KeyStore.getEntry(KeyStore.java:644)
    at MyClass.getKeyStoreEntry(MyClass.java:111)

The source code to create the key pair

Calendar start = Calendar.getInstance();
start.setTimeInMillis(0);
Calendar end = Calendar.getInstance();
end.set(Calendar.YEAR, 3000);

KeyPairGeneratorSpec.Builder keySpecBuilder = new KeyPairGeneratorSpec.Builder(context)
    .setAlias(keyName)
    .setSubject(new X500Principal("CN=" + keyName))
    .setSerialNumber(BigInteger.TEN)
    .setStartDate(start.getTime())
    .setEndDate(end.getTime())
    .setKeySize(RSA_KEY_SIZE);

KeyPairGeneratorSpec spec = keySpecBuilder.build();
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
gen.initialize(spec);
gen.generateKeyPair();

And then to retrieve the key:

private KeyStore.PrivateKeyEntry getKeyStoreEntry() {
    KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
    keyStore.load(null);

    if (!keyStore.containsAlias(keyName)) {
        throw new KeyNotFoundException();
    }
    return (KeyStore.PrivateKeyEntry) keyStore.getEntry(keyName, null);
}

This is only happening when I make use of the KeyPairGeneratorSpec on API level 19-22. The 23+ implementation works fine.

I do not have another key with the same name and I also have not deleted the key.


Solution 1:

I believe you are simply facing Keystore bugs. See this article for example: Android Security: The Forgetful Keystore. There are also numberous bug reports in Android tracker related to keystore, like AndroidKeyStore deleted after changing screen lock type.

Solution 2:

Please use directly getKey method of KeyStore

private java.security.Key getSecretKey(Context context) throws Exception {
  return keyStore.getKey(XEALTH_KEY_ALIAS, null);
}