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:
KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
Everything up to this point is very straight forward and works just fine. Next is where it gets hairy.
KeyStore.getInstance("AndroidKeyStore");
X509Certificate
through an X509V3CertificateGenerator
. This certificate is self signed. For the cert, I set the signature algorithm as "SHA1WithRSAEncryption"
.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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With