The android.security.KeyChain#getCertificateChain needs an alias. But I want to get all installed X509Certificate.
            Asked
            
        
        
            Active
            
        
            Viewed 3,933 times
        
    3 Answers
4
            
            
        You can use something like this to list trusted certificates. Not exactly documented though, so it might break in future versions.
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
ks.load(null, null);
Enumeration aliases = ks.aliases();
while (aliases.hasMoreElements()) {
    String alias = aliases.nextElement();
    X509Certificate cert = (X509Certificate) 
       ks.getCertificate(alias);
    Log.d(TAG, "Subject DN: " + 
       cert.getSubjectDN().getName());
    Log.d(TAG, "Subject SN: " + 
       cert.getSerialNumber().toString());
    Log.d(TAG, "Issuer DN: " + 
       cert.getIssuerDN().getName());
}
        jww
        
- 97,681
 - 90
 - 411
 - 885
 
        Nikolay Elenkov
        
- 52,576
 - 10
 - 84
 - 84
 
4
            
            
        List the available certs:
public void PrintInstalledCertificates( ){
    try 
    {
        KeyStore ks = KeyStore.getInstance("AndroidCAStore");
        if (ks != null) 
        {
            ks.load(null, null);
            Enumeration<String> aliases = ks.aliases();
            while (aliases.hasMoreElements()) 
            {
                String alias = (String) aliases.nextElement();
                java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);
                //To print System Certs only
                if(cert.getIssuerDN().getName().contains(“system”))
                {
                    System.out.println(cert.getIssuerDN().getName());
                }
                //To print User Certs only 
                if(cert.getIssuerDN().getName().contains(“user”))
                {
                    System.out.println(cert.getIssuerDN().getName());
                }
                //To print all certs
                System.out.println(cert.getIssuerDN().getName());                           
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (java.security.cert.CertificateException e) {
        e.printStackTrace();
    }               
}
Check if a certificate is already installed:
public boolean checkCACertificateInstalled(javax.security.cert.X509Certificate x509){
    boolean isCACertificateInstalled = false;
    try 
    {
        String name = x509.getIssuerDN().getName(); 
        KeyStore ks = KeyStore.getInstance("AndroidCAStore");
        if (ks != null) 
        {
            ks.load(null, null);
            Enumeration<String> 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(name)) 
                {
                    isCACertificateInstalled = 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();
    }
    return isCACertificateInstalled;
}
        jww
        
- 97,681
 - 90
 - 411
 - 885
 
        Durai Amuthan.H
        
- 31,670
 - 10
 - 160
 - 241
 
- 
                    1You have to be careful with *Check if a certificate is already installed*. It depends on the `{Distinguished Name, Serial Number}` pair, and not just the `Distinguished Name`. See, for example, [How to troubleshoot “Secure Connection Failed” in Firefox?](http://superuser.com/q/917887/173513) on Super User. In the question, Symantec re-issued a certificate with the same *Distinguished Name* and the same *Subject Public Key*. The only thing that differed was the serial number (and promotion from a Subordinate CA to a Self-Signed Root CA). – jww May 26 '15 at 06:33
 - 
                    1@jww - we can add `cert.getSerialNumber().equals(x509.getSerialNumber())` condition along with `cert.getIssuerDN().getName().contains(name)` to check availability of particular CA. – Durai Amuthan.H May 26 '15 at 07:27
 - 
                    1I think it would be appropriate to return `true` if `{DN,SN}` match. I think it would be a good idea to ***warn*** and possibly return `true` if only `{DN}` match because its probably something unexpected, like a certificate was reissued. Often, the "certificate reissued" is difficult to track down because its using rules that few people know about. For example, the obscure rule for `{DN,SN}` is in [RFC 4158, Certification Path Building](https://tools.ietf.org/rfc/rfc4158.txt). – jww May 26 '15 at 07:35
 - 
                    Oh, and believe it or not... Its `{Issuer DN, SN}` that makes a certificate unique. So maybe more correctly, its the 3-tuple `{Issuer DN, SN, Subject DN}`. That's because certificates don't exist in a vacuum - there's a relationship between the issuer and subject. Its really a mess when things go sideways. Anyway, sorry to complicate the discussion.... – jww May 26 '15 at 07:52
 - 
                    What do you think about comparing the *thumbprints* such as *MD5*,*SHA* between the two certificates ? It'd be even more precise. – Durai Amuthan.H May 26 '15 at 09:08
 - 
                    This is the grey area of "certificate equivalence" (for lack of a better term). Some bits are allowed to change. For example, imagine a certificate expires, and then is re-certified, so the only thing that effectively changes is `notBefore` and `notAfter`. Is that the same certificate for most intents and purposes? – jww May 26 '15 at 09:19
 - 
                    @jww - `{Issuer DN, SN}` would do the job. – Durai Amuthan.H May 26 '15 at 09:32
 
2
            
            
        You cannot - android.security.KeyChain doesn't have any methods to retrieve all aliases, and more importantly - not even the service it communicates with (an implementation of the IKeyChainService AIDL interface in the KeyChain app) exposes a method to list all the aliases - thus the grants and keystore are internal to that app.
        Jens
        
- 16,853
 - 4
 - 55
 - 52
 
- 
                    Thank you. I have another question. How I verify a given x509certificate on Android? I can use the certifcates installed on system or the certificate specific to my application. – crybird Feb 09 '12 at 06:50