Reputation: 1652
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?
Upvotes: 7
Views: 10815
Reputation: 3889
Although there is an accepted answer already, I would like to provide an alternative as it does not provide an actual solution for using pem files directly. It just mentions that the easiest way is to just convert it to a p12 file and use that instead. It is possible to use pem files directly.
I have provided a similar same answer here: How to build a SSLSocketFactory from PEM certificate and key without converting to keystore?
A code example would be:
import nl.altindag.ssl.SSLFactory;
import nl.altindag.ssl.util.PemUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509ExtendedTrustManager;
import java.io.IOException;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) throws IOException {
X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial(Paths.get("/path/to/your/certificate.pem"), Paths.get("/path/to/your/private-key.pem"));
X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial(Paths.get("/path/to/your/some-trusted-certificate.pem"));
SSLFactory sslFactory = SSLFactory.builder()
.withIdentityMaterial(keyManager)
.withTrustMaterial(trustManager)
.build();
HttpClient httpclient = HttpClients.custom()
.setSSLContext(sslFactory.getSslContext())
.build();
HttpGet httpget = new HttpGet("https://my.secure.site.com/url");
HttpResponse response = httpclient.execute(httpget);
System.out.println(response.getStatusLine().getStatusCode());
HttpEntity entity = response.getEntity();
}
}
I need to admit that the solution is based on a library which I have build myself, GitHub - SSLContext Kickstart.
Upvotes: 0
Reputation: 7706
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.
Upvotes: 6
Reputation: 710
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;
}
Upvotes: -1