0

I have been using the keystore to generate RSA key/pair and the code has been working for API levels 18-22. Today when I ran it on API-23, I am not able to retrieve the Private key from the keystore. Below is the code that I have been using:

KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                        .setAlias(utility.getConfigValue(configuration, OuterKeys.KEYSTORE_NAME))
                        .setSubject(
                                new X500Principal("CN=Sample Name, O=Android Authority"))
                        .setSerialNumber(BigInteger.ONE).setStartDate(start.getTime())
                        .setEndDate(end.getTime()).build();
                KeyPairGenerator generator = null;
                generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
                generator.initialize(spec);
                KeyPair keyPair = generator.generateKeyPair();
                PrivateKey privateKey = keyPair.getPrivate();
                PublicKey publicKey = keyPair.getPublic();

                byte[] publicKeyBytes = publicKey.getEncoded();
                String pubKeyStr = Base64.encodeToString(publicKeyBytes, Base64.NO_PADDING);
                byte[] privKeyBytes = privateKey.getEncoded();
                String privKeyStr = Base64.encodeToString(privKeyBytes, Base64.NO_PADDING);

                Log.d("^^^^^^^^^1",pubKeyStr);
                Log.d("^^^^^^^^^2",privKeyStr);

I debugged this and found that the private key generated is null. Whereas I can print the public key string as it is being retrieved. Can anyone help out please.

Sid
  • 1,224
  • 3
  • 23
  • 48
  • Do you mean that you changed the target sdk version to 23, or that you are running it in Android 6.0 device? – 1615903 Mar 04 '16 at 12:27
  • I am running it on a 6.0 device. – Sid Mar 04 '16 at 12:29
  • 3
    `PrivateKey.getEncoded()` is allowed to return null. Looking at the [docs for AndroidKeyStore](http://developer.android.com/training/articles/keystore.html) that seems like the correct behavior. – President James K. Polk Mar 04 '16 at 23:18
  • Thanks for the input. I think the null return is fine and I need to rephrase my question. I am getting an invalid key exception when trying to use the private key to either sign or decrypt any data. I read this question : stackoverflow.com/questions/32400689/… . But the solution doesnt work for me. – Sid Mar 06 '16 at 12:38

1 Answers1

3

It looks like you are retrieving the PrivateKey instance from Android Keystore just fine. You should be able to use this PrivateKey instance with Cipher and Signature primitives just fine too.

What's "not working" is that that PrivateKey instance's getEncoded returns null. As James K Polk mentioned, this is working as intended. getEncoded is supposed to return the private key's key material (usually in PKCS#8 DER-encoded format) or null if key material export is not supported. Android Keystore by design does not reveal/export key material of private keys and thus getEncoded returns null. On older Android platform versions it may have been returning an empty byte array instead.

Alex Klyubin
  • 5,554
  • 2
  • 29
  • 24
  • Thanks for the input. I think the null return is fine and I need to rephrase my question. I am getting an invalid key exception when trying to use the private key to either sign or decrypt any data. I read this question : http://stackoverflow.com/questions/32400689/crash-casting-to-rsaprivatekey . But the solution doesnt work for me – Sid Mar 06 '16 at 12:38
  • Please provide the sample code that reproduces the issue and the full stack trace. Not sure how Stack Overflow prefers it, but it may be best to post all that as a new question or edit the original to include the new information. – Alex Klyubin Mar 06 '16 at 17:29
  • so the problem was that in Marshmallow type casting to RSAPrivateKey is not working. For this question though your answer is perfect. Thanks – Sid Mar 07 '16 at 06:16