问题
i am using the AndroidKeyStore to generate a RSA key pair, which are used to encrypt/decrypt the internal data.
The code which does that is as follows - it tries to retrieve the existing RSA key pair (via an alias ). If none exists then it tries to generate a new one. the code is as -
private void initializePublicPrivateKeys(){
try
{
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(APP_RSA_KEY_PAIR_SECRET_ALIAS, null);
_app_privateRSAKey = entry.getPrivateKey();
_app_publicRSAKey = entry.getCertificate().getPublicKey();
}
catch(Exception e){
}
}
private void initializeRSAKeyPairs() {
initializePublicPrivateKeys();
boolean isKeyNotGenerated = _app_privateRSAKey == null || _app_publicRSAKey == null;
if(isKeyNotGenerated)
{
//Check here, if we already stored some data with previous RSA key pair - if a entry is present in SharedPreference then that would mean we had previously generated a RSA key pair and the entry is in-turn encrypted by this key pair.
generateAppRSAPublicPrivateKeys();
initializePublicPrivateKeys();// initialize it again , since we have new keys generated.
}
}
@TargetApi(18)
private void generateAppRSAPublicPrivateKeys(){
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
// the certificate created would be valid for 25 years. This is just a random value.
cal.add(Calendar.YEAR, 25);
Date end = cal.getTime();
try{
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
Context appContext = getApplicationContext();
KeyPairGeneratorSpec.Builder keyPairGeneratorBuilder =
new KeyPairGeneratorSpec.Builder(appContext)
.setAlias("myrsaalias")
.setStartDate(now)
.setEndDate(end)
.setSerialNumber(BigInteger.valueOf(1))
.setSubject(new X500Principal(String.format("CN=%s, OU=%s", "myrsaalias",
appContext.getApplicationInfo().packageName)));
if(Build.VERSION.SDK_INT >= 19){
keyPairGeneratorBuilder.setKeySize(2048);
}
generator.initialize(keyPairGeneratorBuilder.build());
generator.generateKeyPair();
}
catch(Exception e){
e.printStackTrace();
throw new IllegalArgumentException("Failed to generate RSA Public Private Key pair");
}
}
This code works fine. Once the key pair is generated, I use them to encrypt/decrypt data ( store this data in shared preference ) BUT after certain point of time ( after some app relaunch ) the initializePublicPrivateKeys function fails to retrieve the key pairs.(after this point it fails consistently ) and so what ever data that is stored in the shared preference in encrypted form is lost since i dont have the corresponding public key to decrypt that at all. ( if i generate a new one then, i guess, this would be different and would return incorrect results when i decrypt the data)
I was wondering in what cases this initializePublicPrivateKeys function can fail ?
PS: for now, I can't capture the exception details because the problem is occurring on some customer device which i don't have access to and I need to figure out the source of the problem myself. Also, device password or PIN is not changed during this period ( i confirmed this with my customer )
thanks in advance,
回答1:
Is it possible the user changed their screen lock type to an insecure method such as None or Swipe thus triggering all the keys in the AndroidKeyStore to be deleted? It is a known issue discussed in this blog article: https://doridori.github.io/android-security-the-forgetful-keystore/
Also mentioned here: https://code.google.com/p/android/issues/detail?id=61989
If you do not have strict security requirements and want your app to work even if the user has no screen lock then perhaps just use a keypair stored in a keystore file in your data area and skip the AndroidKeyStore
.
来源:https://stackoverflow.com/questions/30851985/androidkeystore-getentry-is-consistently-failing-after-certain-point