Android 9 - KeyStore exception android.os.ServiceSpecificException

后端 未结 3 599
时光说笑
时光说笑 2020-12-04 18:11

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

private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
        try {
            


        
相关标签:
3条回答
  • 2020-12-04 18:25

    I found a solution how to remove the warning, would be great if you can test it all as well. Actually the order of calling the methods is the problem.

    val privateKey = keyStore.getKey(alias, null)
    val publicKey = if (privateKey != null) keyStore.getCertificate(alias).publicKey else null
    
    if (privateKey != null && publicKey != null) {
        KeyPair(publicKey, privateKey as PrivateKey)
    }
    

    This is the correct ordering of how to call the methods.

    When you do it like this:

    val privateKey = keyStore.getKey(alias, null)
    val certificate = keyStore.getCertificate(alias)
    
    if (privateKey != null && certificate != null) {
        KeyPair(certificate.publicKey, privateKey as PrivateKey)
    }
    

    You will receive the following warning (because of keyStore.getCertificate(alias):

    KeyStore exception
    android.os.ServiceSpecificException:  (code 7)
        at android.os.Parcel.createException(Parcel.java:2085)
        at android.os.Parcel.readException(Parcel.java:2039)
        at android.os.Parcel.readException(Parcel.java:1987)
        at android.security.keystore.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:978)
        at android.security.KeyStore.get(KeyStore.java:236)
        at android.security.KeyStore.get(KeyStore.java:225)
        at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificate(AndroidKeyStoreSpi.java:160)
        at java.security.KeyStore.getCertificate(KeyStore.java:1120)
    

    This means, that there is no private key and you should first create and store a keypair before you search for it in the key store.

    Now with the answer of MatPag it should look like this:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val privateKey = keyStore.getKey(alias, null)
            val publicKey = if (privateKey != null) keyStore.getCertificate(alias).publicKey else null
    
            return if (privateKey != null && publicKey != null) {
                KeyPair(publicKey, privateKey as PrivateKey)
            } else {
                null
            }
    } else {
            val asymmetricKey = keyStore.getEntry(alias, null) as KeyStore.PrivateKeyEntry
            val privateKey = asymmetricKey.privateKey
            val publicKey = if(privateKey != null) asymmetricKey.certificate.publicKey else null
    
            return if(privateKey != null && publicKey != null) {
                KeyPair(publicKey, privateKey as PrivateKey)
            } else {
                null
            }
    }
    
    0 讨论(0)
  • 2020-12-04 18:28

    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();
    
    0 讨论(0)
  • 2020-12-04 18:34

    I had the same problem retrieving an asymmetricKey from AndroidKeyStore

    My solution based on Dr Glass answer to get keys is the following: (aliasKey is your alias string)

    PublicKey:

    val keyStore = KeyStore.getInstance("AndroidKeyStore")
    keyStore.load(null)
    
    val asymmetricPublicKey = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        keyStore.getCertificate(aliasKey).publicKey
    } else {
        val asymmetricKey = keyStore.getEntry(aliasKey, null) as KeyStore.PrivateKeyEntry
        asymmetricKey.certificate.publicKey
    }
    

    PrivateKey:

    val keyStore = KeyStore.getInstance("AndroidKeyStore")
    keyStore.load(null)
    
    val asymmetricPrivateKey = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        keyStore.getKey(aliasKey, null) as PrivateKey
    } else {
        val asymmetricKey = keyStore.getEntry(aliasKey, null) as KeyStore.PrivateKeyEntry
        asymmetricKey.privateKey
    }
    

    and with this code I have no warning in the emulator and/or device with Android P

    0 讨论(0)
提交回复
热议问题