UnrecoverableKeyException Failed to obtain information about private key, KeyStoreException: Invalid key blob : <p>In our app we've been having issues with data in the Android Keystore suddenly becoming inaccessible. The specific exception we're seeing is here:</p>

<pre><code>java.security.UnrecoverableKeyException: Failed to obtain information about private key
 at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:223)
 at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:259)
 at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(AndroidKeyStoreProvider.java:269)
 at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:94)
 at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:474)
 at java.security.KeyStore.getEntry(KeyStore.java:1560)
 at &lt;PACKAGE_NAME&gt;.EncryptionInteractor.generateKeys(EncryptionInteractor.java:104)
 at &lt;PACKAGE_NAME&gt;.EncryptionInteractor.generateKeys(EncryptionInteractor.java:100)
 at &lt;PACKAGE_NAME&gt;.EncryptionInteractor.init(EncryptionInteractor.java:93)
 at &lt;PACKAGE_NAME&gt;.EncryptionInteractor.&lt;init&gt;(EncryptionInteractor.java:80)
 at &lt;PACKAGE_NAME&gt;.EncryptionInteractor.init(EncryptionInteractor.java:65)
 at &lt;PACKAGE_NAME&gt;.&lt;APPLICATION_CLASS&gt;.onCreate(APPLICATION_CLASS.java:17)
 at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1118)
 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5791)
 at android.app.ActivityThread.-wrap1(Unknown Source:0)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1661)
 at android.os.Handler.dispatchMessage(Handler.java:105)
 at android.os.Looper.loop(Looper.java:164)
 at android.app.ActivityThread.main(ActivityThread.java:6541)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.security.KeyStoreException: Invalid key blob
 at android.security.KeyStore.getKeyStoreException(KeyStore.java:695)
 at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:224)
  ... 21 more
</code></pre>

<p>We have not been able to come up with a reliable way of reproducing the issue. Several articles mention possible states that can cause the Keystore to "forget" a Key or become locked such as <a href="https://doridori.github.io/android-security-the-forgetful-keystore/#sthash.SPGO7JXV.wE9npzuE.dpbs" rel="noreferrer">here</a>. However, as far as I can tell we have not fallen into any of these edge cases. It seems to happen after letting the device sit for a while after the first setup of the key. We have seen this happen across multiple emulators and devices, ranging from  21 to 26. Additionally these devices have used either swipe to unlock or a PIN. Changing the PIN or security method does not seem to cause the issue. Again, this issue seems to occur after the device has been sitting unused for several days. </p>

<p>I have found two other SOs <a href="https://stackoverflow.com/questions/36652675/java-security-unrecoverablekeyexception-failed-to-obtain-information-about-priv">here</a> and <a href="https://stackoverflow.com/questions/36488219/android-security-keystoreexception-invalid-key-blob">here</a> as well as one Google <a href="https://issuetracker.google.com/u/1/issues/63786177" rel="noreferrer">issue</a>. If I'm understanding correctly, the answer linked in both seems to rely upon the premise that the caller has called <code>setUserAuthenticationValidityDurationSeconds</code> when creating the Key, and we have not done so. Additionally the given solution seems to rely upon just deleting the key and generating a new one. </p>

<p>Below is our setup for the key on for versions >= API 23. I've left out our key generation for versions older than 23, since we've primarily seen this on APIs >= 23. </p>

<pre><code>private static final int RSA_KEY_SIZE = 2048;
private static final String CERT_SUBJECT_STRING = "CN=&lt;COMPANY_NAME&gt; Android App O=&lt;COMPANY_NAME&gt;";
private static final String ANDROID_KEY_STORE = "AndroidKeyStore";

try {
        String alias = KEY_NAME;
        KeyPairGenerator generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEY_STORE);

        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        end.add(Calendar.YEAR, 1);
        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(RSA_KEY_SIZE, RSAKeyGenParameterSpec.F4))
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
            .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
            .setCertificateNotAfter(end.getTime())
            .setCertificateNotBefore(start.getTime())
            .setCertificateSerialNumber(BigInteger.ONE)
            .setCertificateSubject(new X500Principal(CERT_SUBJECT_STRING))
            .build();
        generator.initialize(spec);
        generator.generateKeyPair();
    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
</code></pre>

<p>We then attempt to access the keys later via <code>keyStore.getEntry(KEY_NAME, null)</code>. Again, this works for a while, but then will begin to throw the above exception.</p>
