IMO the keystore service is unfortunately not in a usable state for applications right now. The reasons are:
- As you've found, Android issue 61989 "AndroidKeyStore deleted after changing screen lock type" (https://code.google.com/p/android/issues/detail?id=61989) which makes everything you store in the keystore service ephemeral. - A security vulnerability I reported to the Android security team in February: keys leak between unrelated app installs in some circumstances (writeup at http://jbp.io/2014/04/07/android-keystore-leak/). The exceptions you've seen are new to me, though. The keystore service and some keymaster backends are pretty chatty; are there any logs associated with each failure? Cheers, Joe On 2 June 2014 22:34, SuSu PePe <[email protected]> wrote: > My Android app need to encrypt app secrets so that it can decrypt and read > it later. This should not be decrypt-able by anybody else other than the > app, even user. > > Following is how I am doing the encryption and decryption. This works most > of the time, but some times for some users this is failing. It is not > specific to a particular handset (Nexus7, Samsung, Motorola, HTC -- all > types are reporting this issue), but not all users are experiencing it. Only > some users occasionally. > > Here is the relevant code (for API > 17) > > encrypt() { > KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); > final KeyStore.PrivateKeyEntry entry; > if (!ks.containsAlias(CERT_ALIAS)) { > Calendar cal = Calendar.getInstance(); > Date now = cal.getTime(); > cal.add(Calendar.YEAR, 50); > Date end = cal.getTime(); > KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", > "AndroidKeyStore"); > kpg.initialize(new > KeyPairGeneratorSpec.Builder(getApplicationContext()) > .setAlias(CERT_ALIAS) > .setStartDate(now) > .setEndDate(end) > .setSerialNumber(BigInteger.valueOf(1)) > .setSubject(new X500Principal("CN=" + CERT_ALIAS)) > .build()); > KeyPair kp = kpg.generateKeyPair(); > } > entry = (KeyStore.PrivateKeyEntry) ks.getEntry( > CERT_ALIAS, null); > pub = entry.getCertificate().getPublicKey(); > // use the pub key to encrypt > } > decrypt() { > KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); > ks.load(null); > > final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) > ks.getEntry( > CERT_ALIAS, null); > PrivateKey key1 = entry.getPrivateKey(); > // use the private key to decrypt > } > > This code sometimes throws > > java.lang.RuntimeException: error:0D07207B:asn1 encoding > routines:ASN1_get_object:header too long > at com.android.org.conscrypt.NativeCrypto.ENGINE_load_private_key(Native > Method) > at > com.android.org.conscrypt.OpenSSLEngine.getPrivateKeyById(OpenSSLEngine.java:66) > at android.security.AndroidKeyStore.engineGetKey(AndroidKeyStore.java:86) > at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372) > at java.security.KeyStore.getEntry(KeyStore.java:644) > > So I modified encrypt() to first try to get the entry and if it raises > exception, generate new key pair. > > final KeyStore.PrivateKeyEntry entry = null; > if (ks.containsAlias(CERT_ALIAS)) { > try { > entry = (KeyStore.PrivateKeyEntry) ks.getEntry( > CERT_ALIAS, null); > } catch (Exception e) { > } > } > if (entry == null) { > //generate new key pair > } > > > But even this is failing sometimes with the following exception. > > java.lang.IllegalStateException: could not generate key in keystore > at > android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100) > at > java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275) > > What am I doing wrong? > How do I fix it/work around it? > Before I generate new pair, should I delete the entry? > (KeyStore.deleteEntry()) > Does this indicate the files (encrypted, wrapped secret key) are tampered? > Does this happen on rooted devices or encrypted devices or when user changes > lock screen PIN/ password? > > ----------- > I tested the following > > Enable Screen lock password > Change it to PIN > > Then > > final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) > ks.getEntry( > CERT_ALIAS, null); > > > getEntry() is returning null. But, not the above exceptions. > > It looks like the key store entry gets deleted when user changes screen lock > password or PIN. Since this is application secret and not user related, I > wonder why? > Is there a way to not get affected by user security settings? > I posted this on Stack Overflow, but thought this might be better place > hence posting here. > http://stackoverflow.com/questions/23965300/android-keystore-getentry-and-generatekeypair-throw-exceptions-sometimes > > -- > You received this message because you are subscribed to the Google Groups > "Android Security Discussions" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to > [email protected]. > Visit this group at http://groups.google.com/group/android-security-discuss. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Android Security Discussions" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/android-security-discuss. For more options, visit https://groups.google.com/d/optout.
