I've connected to bank with two-way SSL (client and server certificate) with Spring Boot. So describe here all my steps, hope it helps someone (simplest working solution, I've found):
Generate sertificate request:
Generate private key:
openssl genrsa -des3 -passout pass:MY_PASSWORD -out user.key 2048
Generate certificate request:
openssl req -new -key user.key -out user.csr -passin pass:MY_PASSWORD
Keep user.key
(and password) and send certificate request user.csr
to bank for my sertificate
Receive 2 certificate: my client root certificate clientId.crt
and bank root certificate: bank.crt
Create Java keystore (enter key password and set keystore password):
openssl pkcs12 -export -in clientId.crt -inkey user.key -out keystore.p12 -name clientId -CAfile ca.crt -caname root
Don't pay attention on output: unable to write 'random state'
. Java PKCS12 keystore.p12
created.
Add into keystore bank.crt
(for simplicity I've used one keystore):
keytool -import -alias banktestca -file banktestca.crt -keystore keystore.p12 -storepass javaops
Check keystore certificates by:
keytool -list -keystore keystore.p12
Ready for Java code:) I've used Spring Boot RestTemplate
with add org.apache.httpcomponents.httpcore
dependency:
@Bean("sslRestTemplate")
public RestTemplate sslRestTemplate() throws Exception {
char[] storePassword = appProperties.getSslStorePassword().toCharArray();
URL keyStore = new URL(appProperties.getSslStore());
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(keyStore, storePassword)
// use storePassword twice (with key password do not work)!!
.loadKeyMaterial(keyStore, storePassword, storePassword)
.build();
// Solve "Certificate doesn't match any of the subject alternative names"
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
RestTemplate restTemplate = new RestTemplate(factory);
// restTemplate.setMessageConverters(List.of(new Jaxb2RootElementHttpMessageConverter()));
return restTemplate;
}