8

Following this blog, I'm using this code to create and store a KeyPair in Android KeyStore:

Context ctx = getApplicationContext();
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
notAfter.add(1, Calendar.YEAR);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(ctx).
setAlias(RSA_KEYS_ALIAS).setSubject(
  new X500Principal(String.format("CN=%s, OU=%s", 
    getApplicationName(), ctx.getPackageName()))).
setSerialNumber(BigInteger.ONE).
setStartDate(notBefore.getTime()).setEndDate(notAfter.getTime()).build();

KeyPairGenerator kpGenerator;
try {
    kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");

    kpGenerator.initialize(spec);
    kpGenerator.generateKeyPair();
} catch (Exception e) {
    showException(e);
}

When I try to retrieve public key from the KeyStore using this code, a NullPointerException with the message chain == null is thrown.

public RSAPublicKey getRSAPublicKey() {
    RSAPublicKey result = null;
    try {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.PrivateKeyEntry keyEntry = 
            (KeyStore.PrivateKeyEntry) keyStore.getEntry(RSA_KEYS_ALIAS, null); // --< exception is thrown here
        result = (RSAPublicKey) keyEntry.getCertificate().getPublicKey();
    }
    } catch (Exception e) {
        showException(e);
    }
    return result;
}

The same goes with the the code to retrieve private key.

Update:

I compared my code with Google BasicAndroidKeyStore sample. The mechanism to generate, store and retrieve the key pair in that sample is virtually the same to what I've implemented. I'm puzzled as to why this code has stopped functioning after a few months of perfectly working.

Any suggestions or hints would be appreciated.

iMan Biglari
  • 4,426
  • 1
  • 30
  • 78

3 Answers3

4

Apparently names in Android KeyStore must be unique amongst all Apps. I had another app which used the same name for its keys. After changing the the common library used by both apps to create and and use keys to include package name in its key names, the problem went away...

iMan Biglari
  • 4,426
  • 1
  • 30
  • 78
  • Just to clarify -- the issue occurred when retrieving the key, not when generating it. So the chain == null was happening when you tried to retrieve the key from a different app than which one generated it? – Johnny C May 23 '17 at 02:42
  • 1
    I know it is an old post, but do you have any reference that says alias should be unique amongst all apps? – Amarghosh May 04 '20 at 15:45
3

In my case, I had multiple calls to obtain the KeyStore at nearly the same time. I had to create a single instance and refer to that if it existed, otherwise KeyStore.getInstance("AndroidKeyStore") returned null and raised an Exception. To protect against multiple async requests causing a crash, use a stored instance from just one KeyStore.getInstance().

Will
  • 21,498
  • 11
  • 84
  • 98
Thomas
  • 290
  • 2
  • 5
  • I had this issue on Android 5 only. I saw this answer and thought... no, surely not. So I tried every other answer, to no avail, and came back to this one in desperation. And what do you know, it worked perfectly! I guess the issue has been fixed in newer Android versions. Don't underestimate this! – Luke Jul 27 '20 at 13:02
0

In my case, I was trying to get public key before generating it. (getRSAPublicKey() called before generateKeyPair())

Saman Sattari
  • 2,330
  • 4
  • 20
  • 35