i have key and cert (combined) into one cert.pem file ,
and i getting ,
"exception": "javax.net.ssl.SSLHandshakeException",
"message": "Received fatal alert: bad_certificate",
pem file is right, but i think problem is how i generating jks keystore file.
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN RSA PRIVATE KEY
...
END RSA PRIVATE KEY###`
keytool -import -trustcacerts -alias yourdomain -file combined.pem -keystore yourkeystore.jks
public class HttpsTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
FileInputStream instream = new FileInputStream(
new File(this.resourcePath()+"/path_to.jks")
);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(instream, "password".toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "password".toCharArray()) // use null as second param if you don't have a separate key password
.build();
sslContext.init(null,new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(
new HttpPost("https://url")
);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(entity);
When you use Apache SSLContexts.custom().loadKeyMaterial().build()
it initializes the built context with the specified keystore and the default trustmanager. You then call sslContext.init()
to re-initialize it with no keymanager and the specified trustmanager; this ignores and discards the prior initialization. As a result your context has no keymanager, and cannot do client auth.
You need to be consistent. Either use Apache and give the (same) builder both loadKeyMaterial
and loadTrustMaterial
corresponding to what you want -- in particular httpclient 4.5.4 adds org.apache.http.conn.ssl.TrustAllStrategy
which implements "cheerfully let all thieves and crooks see and change my supposedly secure data". Alternatively, use JSSE to directly create an SSLContext
with .getInstance()
and .init()
it (once!) with your zero-security trustmanager and a keymanager created from your keystore (and an explicit SecureRandom
if you like but if you omit that it defaults).
However, this may not work because the keytool
command you show is correct only if yourdomain
was a pre-existing PrivateKeyEntry matching the cert chain you imported to it. Use keytool -list -alias yourdomain
to make sure it's a PrivateKeyEntry and NOT a TrustedCertEntry. If not, and if you need to use the privatekey from the PEM file (rather than one already in a keystore) you need to first convert the key and cert chain to PKCS12 with OpenSSL, and then depending on your Java maybe convert the PKCS12 to JKS with keytool
. There are dozens of Qs (and As) on several Stacks for this.