I cannot obtain a (private) key from KeyStore on Android. Problem occurs mainly on Samsung devices (S6, S6 Edge) and Android 6.
android.security.KeyStoreException: Invalid key blob
is thrown when following line is called (where alias is name for store key).
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
The KeyStore itself is obtained by
KeyStore.getInstance("AndroidKeyStore");
And key is generated by the following method:
private static void createKey(String alias, String subject, KeyStore keyStore, BigInteger serialNumber, Date startDate, Date endDate, String algorithm, String keyStoreProvider, Context context)
throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
if (keyStore.containsAlias(alias)) {
// Key already exists.
return;
}
// Generate keys.
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(alias)
.setSubject(new X500Principal(subject))
.setSerialNumber(serialNumber)
.setStartDate(startDate)
.setEndDate(endDate)
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm, keyStoreProvider);
generator.initialize(spec);
KeyPair keyPair = generator.generateKeyPair();
}
Where algorithm is "RSA" and keyStoreProvider is "AndroidKeyStore".
The part of the stacktrace:
android.security.KeyStoreException: Invalid key blob
at android.security.KeyStore.getKeyStoreException(KeyStore.java:939)
at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:216)
at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:252)
at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(AndroidKeyStoreProvider.java:263)
at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:93)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372)
at java.security.KeyStore.getEntry(KeyStore.java:645)
The exception causes java.security.UnrecoverableKeyException: Failed to obtain information about private key to be thrown.
I was not able to find any closer information about "Invalid key blob", only that the message itself is defined here: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/security/keymaster/KeymasterDefs.java
This problem is occurred when user tries to UNLOCK
from LOCK/UNINITIALIZED
. It is by default defined as 30 secs
for timing. This problem is it's API related implementation issue.
This error is generated from InvalidKeyException
. By bypassing this exception and call the method again, you can get rid of this error.
You have to remove the InvalidKeyException
class from the catch argument. This will still allow you to check for InvalidKeyException
. After checking you have to try for second time with code so that the problem is not shown in eye but doing 2 times checking it may solve your issue. Code is given below.
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore
.getEntry("alias", null);
} catch (InvalidKeyException ex) {
ex.printStackTrace();
if (ex instanceof InvalidKeyException) { // bypass
// InvalidKeyException
// You can again call the method and make a counter for deadlock
// situation or implement your own code according to your
// situation
if (retry) {
keyStore.deleteEntry(keyName);
return getCypher(keyName, false);
} else {
throw ex;
}
}
} catch (final Exception e) {
e.printStackTrace();
throw e;
}
You can see my another answer that describes one by one occurring issue and solution.
As you solved the issue by changing InvalidKeyException
to UnrecoverableKeyException
. So I have updated as per your suggestion so that world can know the actual answer. Thanks for sharing :).
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore
.getEntry("alias", null);
} catch (UnrecoverableKeyException ex) {
ex.printStackTrace();
// You can again call the method and make a counter for deadlock
// situation or implement your own code according to your
// situation
if (retry) {
keyStore.deleteEntry(keyName);
return getCypher(keyName, false);
}
} catch (final Exception e) {
e.printStackTrace();
throw e;
}
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