7

I'd like to programmatically access a site that requires Client certificates, which I have in PEM files. In this application I don't want to add them to my keystore, use keytool, or openssl if I can avoid doing so. I need to deal with them directly in code.

    HttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet("https://my.secure.site.com/url");

    // TODO: Specify ca.pem and client.pem here?

    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();

    if (entity != null) {
        entity.consumeContent();
    }

    httpclient.getConnectionManager().shutdown();

How would I 'send' the certificate with the request?

skaffman
  • 390,936
  • 96
  • 800
  • 764
Dave C
  • 1,522
  • 3
  • 23
  • 34

2 Answers2

6

Easiest may well be to use the .p12 format (though the others work fine too - just be careful with extra lines outside the base64 blocks) and add something like:

// systems I trust
System.setProperty("javax.net.ssl.trustStore", "foo");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

// my credentials
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.keyStore", "cert.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");

Or alternatively - use things like

    KeyStore ks = KeyStore.getInstance( "pkcs12" );
    ks.load( new FileInputStream( ....), "mypassword".toCharArray() );

    KeyStore jks = KeyStore.getInstance( "JKS" );
    ks.load(...

to create above on the fly instead. And rather than rely on the system property - use somethng like:

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(aboveKeyStore, "changeme".toCharArray());
    sslContext = SSLContext.getInstance("SSLv3");
    sslContext.init(kmf.getKeyManagers(), null, null);

which keeps it separate from keystore.

DW.

Tommy
  • 3,931
  • 9
  • 35
  • 59
Dirk-Willem van Gulik
  • 7,275
  • 2
  • 33
  • 40
  • 1
    The KeyManagerFactory is the way I needed to go. I really wanted to use a PEM file (since that's what I had). I didn't realize it would be so messy to try and convert it to a different format on the fly. I ended up converting it to DER format using openssl. – Dave C Dec 02 '10 at 21:37
-1

You can create a KeyStore from .pem files like so:

private KeyStore getTrustStore(final InputStream pathToPemFile) throws IOException, KeyStoreException,
        NoSuchAlgorithmException, CertificateException {
    final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null);

    // load all certs
    for (Certificate cert : CertificateFactory.getInstance("X509")
            .generateCertificates(pathToPemFile)) {
        final X509Certificate crt = (X509Certificate) cert;

        try {
            final String alias = crt.getSubjectX500Principal().getName();
            ks.setCertificateEntry(alias, crt);
            LOG.info("Added alias " + alias + " to TrustStore");
        } catch (KeyStoreException exp) {
            LOG.error(exp.getMessage());
        }
    }

    return ks;
}
shreyas
  • 700
  • 8
  • 10
  • This code did not work for me because: (1) pem files have `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` that needs to be removed before `generateCertificates()` can be done; (2) it does not take into consideration the private key embedded in the `.pem` file. Correct solution is available here: http://stackoverflow.com/questions/12501117/programmatically-obtain-keystore-from-pem – Subhash Chandran Jul 23 '16 at 18:15