How to save a key using an Android key storage device

I am trying to use the Android keystore provider, which became available in Android 4.3, to safely store the private key, and then use this private key to encrypt and decrypt data.

I think I have applied the correct approach and the code for this so far, however, at present I am facing an odd problem that I cannot understand.

I have a KeyStorage class that I use to create a key pair, load a KeyStore and get a 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(); } 

Then I have a class called CredentialStore in which I try to use this. I am creating an alias called "MySecureKey" and am trying to create and save a private key based on this. That way, as you can see, I'm trying to create a new key pair based on loading Alias, the keystore, and then finally getting the secret key. However, this does not 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 follows:

 Aliases = MySecureKey Could not find key alias: MySecureKey 

So, when I check the aliases in the loadKeyStore method, it looks like it is returning to the log. However, when I try to call it using the loadKeyStore method, I get a message stating that it cannot find the key "MySecureKey".

I can't find a reason for this, and researching online has been fruitless, so I was wondering if anyone had any idea what might be wrong?

+8
android encryption android-keystore private-key
source share
3 answers

Why is this blueBirdKeyStore in:

 blueBirdKeyStorage.loadKeyStore(); 

Must not be:

 keyStorage.loadKeyStore(); 

Also, you did not use an "alias" in your loadPrivateKey ():

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

Now, I'm not sure, but shouldn't you use an alias in this?

+1
source share

Your method of checking for your key is erroneous:

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

According to javadoc .isKeyEntry() has the following behavior

Returns true if the record identified by this alias created a setKeyEntry call or created a setEntry call using PrivateKeyEntry or SecretKeyEntry.

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

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

it will not be zero.

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

+1
source share

loadPrivateKey in your class does not use an "alias" to extract the key. It uses a different class constant, so I'm not sure what you expect here.

0
source share

All Articles