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.