Android
Android

Reputation: 3868

Detect installed certificate in my android device

I am installing a certificate in my application when application starts. I have gone through few of the links as below and successfully install the certificate.

I came to know we cannot install the certificate silently without user interaction.Currently I don't know how to stop prompt each time user open my app.

Whenever my application starts currently every time it ask user to install certificate. Is there some way I can detect whether a certificate(in this case my certificate) is already installed or not, programmatically.

Code snippet where I have installing certificate in my app

private void installCertificate()
    {
        try 
        {
            BufferedInputStream bis = new BufferedInputStream(getAssets().open(MY_CERT));
            byte[] keychain = new byte[bis.available()];
            bis.read(keychain);

            Intent installIntent = KeyChain.createInstallIntent();
            X509Certificate x509 = X509Certificate.getInstance(keychain);
            installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, x509.getEncoded());
            installIntent.putExtra(KeyChain.EXTRA_NAME, MY_CERT);
            startActivityForResult(installIntent, INSTALL_KEYCHAIN_CODE);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        catch (CertificateException e) 
        {
            e.printStackTrace();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
        if (requestCode == INSTALL_KEYCHAIN_CODE) 
        {
            switch (resultCode) 
            {  
                case Activity.RESULT_OK:
                    doTheTask();
                    break;
                case Activity.RESULT_CANCELED:
                    finish();
                    break;                  
                default:
                    super.onActivityResult(requestCode, resultCode, data);
            }
        }
    }

Also FYI, installCertificate() is called from onCreate().

Please help me out for the same. Any help will appreciated.


Query: When prompt comes for certificate name, entered text comes as selected and on orientation change cut/copy option comes. Any body knows how to stop text selection when prompt comes?!!!

Upvotes: 18

Views: 11249

Answers (5)

Job
Job

Reputation: 123

This is the Kotlin version of how to list all user-installed CA certificates on an Android device. If you change "user" to "system" you'll get the pre-installed CA certificates instead. If you don't want this distinction you can remove the filter.

val userInstalledCaCertificates: List<X509Certificate> = try {
  val keyStore = KeyStore.getInstance("AndroidCAStore")
  keyStore.load(null, null)
  val aliasList = keyStore.aliases().toList().filter { it.startsWith("user") }
  aliasList.map { keyStore.getCertificate(it) as X509Certificate }
} catch (e: Exception) {
  emptyList()
}

Upvotes: 2

Android
Android

Reputation: 3868

I used the below piece of Java code to check whether or not my certificate is installed:

try
{
    KeyStore ks = KeyStore.getInstance("AndroidCAStore");
    if (ks != null) 
    {
        ks.load(null, null);
        Enumeration aliases = ks.aliases();
        while (aliases.hasMoreElements()) 
        {
            String alias = (String) aliases.nextElement();
            java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);

            if (cert.getIssuerDN().getName().contains("MyCert")) 
            {
                isCertExist = true;
                break;
            }
        }
    }
} catch (IOException e) {
    e.printStackTrace();
} catch (KeyStoreException e) {
    e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (java.security.cert.CertificateException e) {
    e.printStackTrace();
}

Upvotes: 23

Tragalunas
Tragalunas

Reputation: 311

Adding some additional info to @Android's answer (I cannot comment yet), whose code worked for me only in devices with Android 4.0 or higher.

For devices pre IceCream Sandwich (API < 14):

boolean isCertExist;
    TrustManagerFactory tmf;
    try {
        tmf = TrustManagerFactory.getInstance(TrustManagerFactory
                .getDefaultAlgorithm());

        tmf.init((KeyStore) null);

        X509TrustManager xtm = (X509TrustManager) tmf.getTrustManagers()[0];
        for (X509Certificate cert : xtm.getAcceptedIssuers()) {
            if (cert.getIssuerDN().getName().contains("MyCert")) {
                isCertExist = true;
                break;
            }
        }
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

For devices with Android 4.0 and upwards (API >= 14):

boolean isCertExist;
    try 
    {
        KeyStore ks = KeyStore.getInstance("AndroidCAStore");
        if (ks != null) 
        {
            ks.load(null, null);
            Enumeration aliases = ks.aliases();
            while (aliases.hasMoreElements()) 
            {
                String alias = (String) aliases.nextElement();
                java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);

                if (cert.getIssuerDN().getName().contains("MyCert")) {
                    isCertExist = true;
                    break;
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (java.security.cert.CertificateException e) {
        e.printStackTrace();
    }

Upvotes: 4

Konjengbam
Konjengbam

Reputation: 119

Reading off from trusted CA store as below

KeyStore ks = KeyStore.getInstance("AndroidCAStore");

will only fetch the CA certificates and not the user/client certificates. It is not necessary that client certificate share the same alias as that of the CA certificate.

Upvotes: 0

Mark Chen
Mark Chen

Reputation: 11

KeyChain.createInstallIntent, the created intent will call android.security.certinstaller to install certificates, then the certinstaller will print log when certificates are installed. so you can dump the log cat to check whether certificate is installed or not.(you can get the alias if user changed the store name of certificate)

Upvotes: 1

Related Questions