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)


   1. What am I doing wrong?
   2. How do I fix it/work around it?
   3. Before I generate new pair, should I delete the entry? 
   (KeyStore.deleteEntry())
   4. Does this indicate the files (encrypted, wrapped secret key) are 
   tampered?
   5. 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 android-security-discuss+unsubscr...@googlegroups.com.
To post to this group, send email to android-security-discuss@googlegroups.com.
Visit this group at http://groups.google.com/group/android-security-discuss.
For more options, visit https://groups.google.com/d/optout.

Reply via email to