Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android KeyStore System - Saving a KeyPair?

I am currently attempting to put together a functioning KeyStore implementation in my Android application. I am currently building against a minimum API of 18 so that I can fully take advantage of a private KeyStore for my app. I am attempting to generate n number of KeyPair objects, and save them in the KeyStore for later retrieval. I have looked at this question, however it seems a bit outdated (2012) and does not really answer anything all that well. Honestly, most of the questions I've found on Stack Overflow seem to be incredibly outdated, like here and here.

So my intended flow is this:

  1. Attempt to retrieve a public key from the certificate correllating with the appropriate alias.
  2. In the event that this public key is null, create a new key.
  3. Utilize KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
  4. Generate the key pair.

Everything up to this point is very straight forward and works just fine. Next is where it gets hairy.

  1. Save the key pair. Initialize the KeyStore via KeyStore.getInstance("AndroidKeyStore");
  2. Attempt to generate an X509Certificate through an X509V3CertificateGenerator. This certificate is self signed. For the cert, I set the signature algorithm as "SHA1WithRSAEncryption".
  3. Finally, call keyStore.setKeyEntry

For this last step there seem to be two options:

keyStore.setKeyEntry(String alias, byte[] key, Certificate[] chain);

or

keyStore.setKeyEntry(String alias, Key key, char[] password, Certificate[] chain);

I started with the second of the two, but received java.security.KeyStoreException: entries cannot be protected with passwords .... Okay, that's odd, why would there be a method that guarantees to throw an exception? Let's try door number 1.

At which point, when I call setKeyEntry, and pass keyPair.getPrivate().getEncoded() as the second argument, I receive java.security.KeyStoreException: Operation not supported because key encoding is unknown from the system.

So I'm kind of at a loss. Encryption like this is relatively new to me, so I was hoping that someone could shed some light on the very confusing situation that is the Android KeyStore system.

like image 760
Elli White Avatar asked Aug 11 '15 17:08

Elli White


2 Answers

So I have found the answer - hopefully this will help save some issues for future users, as it is not clearly laid out in the docs.

The KeyPairGeneratorSpec.Builder has a method setAlias. When a key is generated, it is automatically stored in the KeyStore under this alias. there is no extra saving that needs to happen to make it work. You can then easily retrieve these keys through instantiating the KeyStore with the same String provider as you did the KeyPairGenerator.

like image 136
Elli White Avatar answered Oct 13 '22 01:10

Elli White


I was trying to import a PKCS12 file (say downloaded by user manually) into AndroidKeyStore. It seems that

keyStore.setKeyEntry(String alias, byte[] key, Certificate[] chain);

is not implemented by AndroidKeyStore and it always throws the following exception:

KeyStoreException("Operation not supported because key encoding is unknown")

Ref: https://android.googlesource.com/platform/frameworks/base.git/+/android-5.1.1_r19/keystore/java/android/security/AndroidKeyStore.java

@Override
    public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
            throws KeyStoreException {
        throw new KeyStoreException("Operation not supported because key encoding is unknown");
    }

So, I tried using

keyStore.setKeyEntry(String alias, Key key, char[] password, Certificate[] chain);

by passing password as null. It worked fine for me.

like image 39
garnet Avatar answered Oct 12 '22 23:10

garnet