Hey,
In my app we are using RSA key, that the app generate (using android key store) on the first launch. From unknown reason, the app failed to retrieved the key from the key store on some of the devices. I've checked the logs, and I could not find a correlation between this bug to a specific OS version or to a specific device model. Also, I know for sure the app tried to read it only after the key created. So - my question is that: As far as I know, android key store should be persistent, what can cause such a bug?
Bellow are relevant code samples.
Key generation:
try {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", keyStore.getProvider());
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
KeyGenParameterSpec spec;
spec = new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT| KeyProperties.PURPOSE_SIGN| KeyProperties.PURPOSE_VERIFY)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
.setKeySize(2048)
.build();
generator.initialize(spec);
} else {
Calendar start = new GregorianCalendar();
Calendar end = new GregorianCalendar();
end.add(Calendar.YEAR, 500);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(alias)
.setSubject(new X500Principal("CN="+ subject))
.setSerialNumber(BigInteger.valueOf(new Random().nextInt(Integer.MAX_VALUE)))
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.setKeySize(2048)
.build();
generator.initialize(spec);
}
return generator.generateKeyPair();
} catch (Exception e) {
logger.warn("Failed to create private key in store", e);
return null;
}The keystore itself intialized using the following code:
KeyStore androidKeyStore = KeyStore.getInstance("AndroidKeyStore");
androidKeyStore.load(null);
return androidKeyStore;And we use the following code to retrieve the key, the bug is that on some devices the keystore returns null:
try {
Key key = keyStore.getKey(alias, null);
if (key == null){
logger.warn("Key not found in key store");
return null;
}
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keyStore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
return new KeyPair(publicKey, (PrivateKey) key);
} else {
logger.warn("Key found, but not from current type. type found: " + key.getClass().getSimpleName());
}
return null;
}catch (Exception e){
logger.warn("Failed to get private key in store", e);
return null;
}The question also posted as SO:
http://stackoverflow.com/questions/37920232/android-keystore-keys-not-always-persisted
Thanks,
Omer