Android P - KeyStore exception android.os.ServiceS

2019-02-04 22:26发布

问题:

If I run this code on Android P, I receive the follow exception:

private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
        try {
            KeyStore ks = KeyStore
                    .getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
            ks.load(null);
            KeyStore.Entry entry = ks.getEntry(alias, null);

            if (entry == null) {
                Log.w(TAG, "No key found under alias: " + alias);
                Log.w(TAG, "Exiting signData()...");
                return null;
            }

            if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
                Log.w(TAG, "Not an instance of a PrivateKeyEntry");
                Log.w(TAG, "Exiting signData()...");
                return null;
            }
            return (KeyStore.PrivateKeyEntry) entry;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return null;
        }
    }

Exception:

KeyStore exception android.os.ServiceSpecificException: (code 7) at android.os.Parcel.createException(Parcel.java:1956) at android.os.Parcel.readException(Parcel.java:1910) at android.os.Parcel.readException(Parcel.java:1860) at android.security.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:786) at android.security.KeyStore.get(KeyStore.java:195) at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificateChain(AndroidKeyStoreSpi.java:118) at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:484) at java.security.KeyStore.getEntry(KeyStore.java:1560) at com.phenodev.testenc.KeyStoreHelper.getPrivateKeyEntry(KeyStoreHelper.java:151) at com.phenodev.testenc.KeyStoreHelper.encrypt(KeyStoreHelper.java:173) at com.phenodev.testenc.KeyStoreEncryptor.encrypt(KeyStoreEncryptor.java:19)

Please help to fix it.

回答1:

Finally I found a solution. It looks like since Android P (KeyStore.PrivateKeyEntry) keyStore.getEntry("alias", null) is not a proper way to get private key.

I was able to get rid of this warning by accessing private/public key this way

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);

PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", null);
PublicKey publicKey = keyStore.getCertificate("alias").getPublicKey();


回答2:

In my case, the warning was still there even getting the keys as the accepted solution, but only when the key did not yet exist.

The warning comes from the getCertificate call, so, to avoid it:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);

PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", null);
PublicKey publicKey = privateKey != null ? keyStore.getCertificate("alias").getPublicKey() : null;