8

I am trying to use the Android Key Store Provider that became available in Android 4.3 to securely save a Private Key and to then use this private key to encrypt and decode data.

I think I have implemented the correct approach and code for this so far however I am currently facing an odd issue that I cannot figure out.

I have a class called KeyStorage that I use to create the Key pair, load the KeyStore and retrieve the private key, the code for this class is as follows:

public class KeyStorage {

public static final String ANDROID_KEYSTORE = "AndroidKeyStore";
private KeyStore keyStore;

public void loadKeyStore() {
    try {
        keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
        keyStore.load(null);
        Enumeration<String> aliases = keyStore.aliases();
        while(aliases.hasMoreElements())
            Log.e("E", "Aliases = " + aliases.nextElement());
    } catch (Exception e) {
        // TODO: Handle this appropriately in your app
        e.printStackTrace();
    }
}

public void generateNewKeyPair(String alias, Context context)
        throws Exception {

    Calendar start = Calendar.getInstance();
    Calendar end = Calendar.getInstance();
    // expires 1 year from today
    end.add(1, Calendar.YEAR);

    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
            .setAlias(alias)
            .setSubject(new X500Principal("CN=" + alias))
            .setSerialNumber(BigInteger.TEN)
            .setStartDate(start.getTime())
            .setEndDate(end.getTime())
            .build();

    // use the Android keystore
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", ANDROID_KEYSTORE);
    gen.initialize(spec);

    // generates the keypair
    gen.generateKeyPair();
}

public PrivateKey loadPrivteKey(String alias) throws Exception {

    if (keyStore.isKeyEntry(alias)) {
        Log.e("E", "Could not find key alias: " + alias);
        return null;
    }

    KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);

    if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
        Log.e("E", " alias: " + alias + " is not a PrivateKey");
        return null;
    }

    return ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
}

I then have a class called CredentialStore that I try to use this in. I create an alias called "MySecureKey" and try to create and store a private key based on this. So as you can see I try to create the new Key pair based on the Alias load the keystore and then finally retrieve the Private key. However it doesn't work.

public class CredentialStore {

public static final String KEY_ALIAS  = "MySecureKey";

private KeyStorage KeyStorage;

public CredentialStore(Activity context){

    keyStorage = new KeyStorage();
    try {
        keyStorage.generateNewKeyPair(KEY_ALIAS, context);
    } catch (Exception e) {
        e.printStackTrace();
    }
    blueBirdKeyStorage.loadKeyStore();

    try {
        keyStorage.loadPrivteKey(KEY_ALIAS);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

I get the logs as follow:

Aliases = MySecureKey
Could not find key alias: MySecureKey

So when I check the aliases in the loadKeyStore method it looks like it is there as it is coming back in the log. However when I try to call it using the loadKeyStore method I get the log saying it can not find the key "MySecureKey".

I cannot find any reason for this and researching online has proven unfruitful so I was wondering if anyone has any idea what might be going wrong?

2
  • 4
    1. You generate KeyPair and don't make use of it. Your generateNewKeyPair method doesn't return anything. 2. You don't save anything to KeyStore to load it later. please refer to a sample on KeyStore useage. It might help you developer.android.com/samples/BasicAndroidKeyStore/index.html Commented Sep 25, 2014 at 16:25
  • @AlexanderZhak altough the many upvotes, your comment is wrong: check out the official doc: developer.android.com/training/articles/… this is how you use the Android Keystore - it is not necessary to put the key explicitly if you use the KeyFactory with the Android Keystore instance. Commented Sep 21, 2016 at 11:51

3 Answers 3

1

Why is it blueBirdKeyStore in:

blueBirdKeyStorage.loadKeyStore();

Shouldn't it be:

keyStorage.loadKeyStore();

Also, you haven't used the 'alias' in your loadPrivateKey():

KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);

Now, I'm not sure, but shouldn't you be using the 'alias' in this?

Sign up to request clarification or add additional context in comments.

Comments

1

Your method to check if your key exists is flawed:

if (keyStore.isKeyEntry(alias)) {
    Log.e("E", "Could not find key alias: " + alias);
    return null;
}

According to the javadoc .isKeyEntry() has the following behavior

Returns true if the entry identified by the given alias was created by a call to setKeyEntry, or created by a call to setEntry with a PrivateKeyEntry or a SecretKeyEntry.

but your key was not created through setEntry(). I guess if you just load the key with

KeyStore.Entry entry = ks.getEntry(alias, null);

it won't be null.

Here is a full example with simple methods on how to use the Android Keystore with pre-M and M Apis.

Comments

0

loadPrivateKey in your class does not use the "alias" to retrieve the key. It's using another class's constant so I'm not sure what's you're expecting here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.