Question

This is similar to Import PEM into Java Key Store. But the question's answers use OpenSSL for conversions and tools to import them into key stores on the file system.

I'm trying to use a well formed X509 certificate as a trust anchor:

static String CA_FILE = "ca-rsa-cert.pem";

public static void main(String[] args) throws Exception
{
    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream(CA_FILE), null);

    TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);

    // Redirected through hosts file
    URL url = new URL("https://example.com:8443");

    HttpsURLConnection connection = (HttpsURLConnection) url
            .openConnection();
    connection.setSSLSocketFactory(context.getSocketFactory());

    ...
}

When I attempt to run the program, I get an error:

$ java TestCert 
Exception in thread "main" java.io.IOException: Invalid keystore format
    at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:650)
    at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
    at java.security.KeyStore.load(KeyStore.java:1214)
    at TestCert.main(TestCert.java:30)

I also tried KeyStore ks = KeyStore.getInstance("PEM"); and getInstance("X509");, but they did not work either.

I know Java supports PEM and DER encoded certificates because that's what a web server sends to a client. But none of the KeyStoreType's seem to match my needs, so I suspect I'm not using the right APIs for this.

The reasons I want to use them directly and not import them into a long-lived KeyStore are:

  1. There are hundreds of PEM certs to test
  2. The certs are on my filesystem
  3. Using certs from the filesystem matches my workflow
  4. I don't want to to use openssl or keytool
  5. I don't want to perform key store maintenance

How does on take a well formed PEM encoded certificate on the filesystem and use it directly?

Was it helpful?

Solution

I found the answer while trying to do this another way at Set certificate for KeyStore.TrustedCertificateEntry?. Its based on Vit Hnilica's answer at loading a certificate from keystore. I"m going to leave the question with this answer since most Stack Overflow answers start with "convert with openssl, then use keytool ...".

String CA_FILE = ...;

FileInputStream fis = new FileInputStream(CA_FILE);
X509Certificate ca = (X509Certificate) CertificateFactory.getInstance(
        "X.509").generateCertificate(new BufferedInputStream(fis));

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry(Integer.toString(1), ca);

TrustManagerFactory tmf = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top