39

I would like to be able to get access to all trusted root certificates programmatically in a Java app.

I was looking at the keystore interface, but I'm hoping to get the list of trusted roots that's implicit with the JRE.

Is this accessible anywhere?

Shawn D.
  • 7,895
  • 8
  • 35
  • 47

3 Answers3

42

There's an example that shows how to get a Set of the root certificates and iterate through them called Listing the Most-Trusted Certificate Authorities (CA) in a Key Store. Here's a slightly modified version that prints out each certificate (tested on Windows Vista).

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Iterator;


public class Main {

    public static void main(String[] args) {
        try {
            // Load the JDK's cacerts keystore file
            String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
            FileInputStream is = new FileInputStream(filename);
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            String password = "changeit";
            keystore.load(is, password.toCharArray());

            // This class retrieves the most-trusted CAs from the keystore
            PKIXParameters params = new PKIXParameters(keystore);

            // Get the set of trust anchors, which contain the most-trusted CA certificates
            Iterator it = params.getTrustAnchors().iterator();
            while( it.hasNext() ) {
                TrustAnchor ta = (TrustAnchor)it.next();
                // Get certificate
                X509Certificate cert = ta.getTrustedCert();
                System.out.println(cert);
            }
        } catch (CertificateException e) {
        } catch (KeyStoreException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (InvalidAlgorithmParameterException e) {
        } catch (IOException e) {
        } 
    }
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • 1
    ok, I'll try this out. (time passes) It worked. You know, what's sad is that the password for the default keystore really is 'changeit'. Thanks. – Shawn D. Aug 18 '10 at 03:25
  • 8
    You know of a better password for the default keystore? – Thorbjørn Ravn Andersen Aug 18 '10 at 03:56
  • is there a way to change the default password?? – Jaime Hablutzel May 13 '11 at 17:14
  • 1
    @jaime: You can change it using keytool. http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html – Bill the Lizard May 13 '11 at 17:18
  • This is likely to work most of the time, but is not guaranteed: http://stackoverflow.com/a/8885263/372643 – Bruno May 01 '12 at 12:24
  • 3
    This code has significant limitations, IMO. For example, if the default truststore is set using system properties (javax.net.ssl.trustStore, javax.net.ssl.trustStorePassword, javax.net.ssl.trustStoreType, etc), then this code will end up loading the wrong trust store. This type of code will also cause issues in environments in which the default truststore has been replaced with something like NSS (for FIPS compliance). – jsight Nov 29 '12 at 18:56
  • 1
    @Bill - "This class retrieves the most-trusted CAs from the keystore" - please forgive my ignorance... what does "most-trusted" mean? – jww Apr 27 '14 at 23:04
  • @jww "most-trusted" in this case just refers to a trust anchor (https://en.wikipedia.org/wiki/Trust_anchor). In the above example, this would be the trusted CA's, or the authorities that issue/sign the certificates of a site you might visit or URL you might interact with. – josh-cain Nov 11 '15 at 18:24
  • 1
    `Exampledepot.com` is for sale now (2018). But this link seems fine http://www.java2s.com/Tutorial/Java/0490__Security/ListingtheMostTrustedCertificateAuthoritiesCAinaKeyStore.htm – datafiddler Mar 14 '18 at 10:52
20

This should be more flexible using the default trust store in the system to get all certificates:

TrustManagerFactory trustManagerFactory =
   TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
List<Certificate> x509Certificates = new ArrayList<>();
trustManagerFactory.init((KeyStore)null);                 
Arrays.asList(trustManagerFactory.getTrustManagers()).stream().forEach(t -> {
                    x509Certificates.addAll(Arrays.asList(((X509TrustManager)t).getAcceptedIssuers()));
                });

```

k_o_
  • 5,143
  • 1
  • 34
  • 43
0

A working example, combining concept from Bill the Lizard and k_o_ answer:

import java.io.FileInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.X509Certificate;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class JDKTrustStoreCertListing {

    public static void main(String[] args) throws Exception{
        
        String javaHome=System.getProperty("java.home");
        Path jdkCACertPath=Paths.get(javaHome, "lib", "security", "cacerts");
        
        TrustManagerFactory trustManagerFactory=TrustManagerFactory
                                                    .getInstance(TrustManagerFactory
                                                                    .getDefaultAlgorithm());
        
        FileInputStream fis=new FileInputStream(jdkCACertPath.toFile());
        String keystorePassword="changeit";
        
        KeyStore keyStore=KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(fis, keystorePassword.toCharArray());

        fis.close();
        
        trustManagerFactory.init(keyStore);
        
        TrustManager[] truestManagers=trustManagerFactory.getTrustManagers();
        for(TrustManager t:truestManagers)
            for(X509Certificate c:((X509TrustManager)t).getAcceptedIssuers())
                    System.out.println(c.getIssuerX500Principal());
    
    }//main closing

}//class closing
Ironluca
  • 3,402
  • 4
  • 25
  • 32