Skip to content

Common Issues With AndroidKeyStore

nicolette edited this page Mar 23, 2017 · 3 revisions

Context

LockScreen type change

There has been issue reported that when lockscreen type is changed, it could potentially cause the keystore to be wiped out. The following are the two top exceptions that could be thrown due to the above issue:

Caused by: java.security.InvalidKeyException: javax.crypto.BadPaddingException: 
         error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
Caused by: java.lang.IllegalArgumentException: key.length == 0

Issues reported to google: Issue 61989: AndroidKeyStore deleted after changing screen lock type https://code.google.com/p/android/issues/detail?id=61989

Remote service attempts to access Keystore

There is an issue with Android Keystore when remote service attempts to access Keystore. Changeset found for google source to address the related issue with remote service accessing keystore https://android.googlesource.com/platform/external/sepolicy/+/0e30164b17af20f680635c7c6c522e670ecc3df3 The thrown exception in this case is:

java.lang.NullPointerException: Attempt to invoke interface method 
    'int android.security.IKeystoreService.exist(java.lang.String, int)' on a null object reference

Key store issue with Arabic or Persian

When keystore generates the key pair, it generates a self signed cert. The ASN1 parser used internally by Android Keystore doesn't correctly take in the locale and it causes the failures for device locale with language from right to left. Sample stack trace:

Caused by: java.lang.IllegalArgumentException: invalid date string: Unparseable date: "÷ððñðñððððððGMT+00:00" 
    at com.android.org.bouncycastle.asn1.ASN1UTCTime.<init>(ASN1UTCTime.java:115)
    at com.android.org.bouncycastle.asn1.DERUTCTime.<init>(DERUTCTime.java:23)
    at com.android.org.bouncycastle.asn1.x509.Time.<init>(Time.java:67)
    at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateSelfSignedCertificateWithFakeSignature(AndroidKeyStoreKeyPairGeneratorSpi.java:696)

Issues reported to google: https://code.google.com/p/android/issues/detail?id=207613

Mitigation

The long term goal is to use hardware key persistence like TPM in windows.Before we can get that in the library, we require all the apps that use ADAL to pass us the encryption key.

How to pass the Encryption key

Use the following API to set the encryption key AuthenticationSettings.Instance.setSecretyKey(byte[])

Note:

  1. Most of the apps today only supply the encryption key for API version less than 18 and use AndroidKeyStore for 18 and above. There is no need to worry the upgrade scenario, ADAL itself handles the scenario.
  2. The symmetric key passed in has to be the same for the lifetime of the app. If the passed in symmetric key is changed, we won't be able to decrypt the encrypted blob. DigestException will be thrown.
  3. If the app has multiple running processes and the acquireToken calls are made in multiple processes, App needs to make sure that the key is the same across process.

Additional Note on the key

  1. The passed in encryption key has to be 32 byte.
  2. ADAL takes in the raw bytes of the key, App can choose its own algorithm for key generation.

Sample code for key generation

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
SecretKey generatedSecretKey = keyFactory.generateSecret(new PBEKeySpec(your_password, byte-code-for-your-salt, 100, 256));
SecretKey secretKey = new SecretKeySpec(generatedSecretKey.getEncoded(), algorithm);
AuthenticationSettings.INSTANCE.setSecretKey(secretKey.getEncoded());
Clone this wiki locally