I am trying to understand how to configure the Web client. What I have is a working curl that I am not able to convert into a valid HTTPS request through (any) Java HTTP client. The curl is:
curl -s --cert $CERTIFICATE --key $KEY https.url
where $CERTIFICATE is a .crt
file containing:
----BEGIN CERTIFICATE----
....
----END CERTIFICATE-----
And the $KEY is a .key
file containing:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
I want to convert this curl into a valid JAVA request. Currently, I am configuring a Spring WebClient in this way:
private WebClient getWebClient() throws SSLException {
SslContext sslContext = SslContextBuilder.forClient().keyManager(
Paths.get(properties.getCrtFile()).toFile(),
Paths.get(properties.getKeyFile()).toFile(),
properties.getCertKeyPassword()).build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext));
return WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
}
But when I use the webclient to make a request it returns an error:
exception: File does not contain valid private key:
Any idea where is the error?
CodePudding user response:
This is how I solved the problem:
- Verify that
.cert
and.key
files are valid:
openssl x509 -noout -modulus -in certFile.crt | openssl md5
#> (stdin)= 7f1a9c4d13aeaddd77fd4a0f241a6ce8
and
openssl rsa -noout -modulus -in certKey.key | openssl md5
#> (stdin)= 7f1a9c4d13aeaddd77fd4a0f241a6ce8
- Convert my
.cert
and.key
files into aPCKS12
that Java can understand. (Keep in mind that my cert and key files are in PEM format as explained in the question). I used the following command:
openssl pkcs12 -export -in certFile.crt -inkey keyFile.key -out cert.p12
This step will prompt you to enter a password. We will use this password when reading the certificate into a KeyStore.
- Create an SSLContext by reading the certificate:
private SslContext getSSLContext() {
try (FileInputStream keyStoreFileInputStream = new
FileInputStream("pathTop12CertificateFile")) {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyStoreFileInputStream,"password".toCharArray());
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
return SslContextBuilder.forClient()
.keyManager(keyManagerFactory)
.build();
} catch (Exception e) {
log.error("An error has occurred: ", e);
}
return null;
}
- Build a Spring WebClient using this SSLContext:
private WebClient getWebClient() {
HttpClient httpClient = HttpClient.create().secure(sslSpec -> sslSpec.sslContext(getSSLContext()));
ClientHttpConnector clientHttpConnector = new ReactorClientHttpConnector(httpClient);
return WebClient
.builder()
.clientConnector(clientHttpConnector)
.build();
}
Now we can use WebClient to make our HTTP Requests.
CodePudding user response:
From the details you provided, I understand that the SslContextBuilder
can't understand your key type.
Try to convert a non-encrypted key to PKCS8 using the following command.
openssl pkcs8 -topk8 -nocrypt -in pkcs1_key_file -out pkcs8_key.pem
Also, see the examples at https://netty.io/4.0/api/io/netty/handler/ssl/util/InsecureTrustManagerFactory.html that accepts without verification all X.509 certificates, including those that are self-signed.
Also discussed at https://groups.google.com/forum/#!topic/grpc-io/5uAK5c9rTHw