У меня есть приложение Java, которое использует сертификаты от смарт-карты для аутентификации клиента TLS / SSL.
Смарт-карта имеет 2 сертификата, один для подписи, а другой для аутентификации. Вот как я это делаю:
// loading windows-my store
KeyStore windowsMyKeyStore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
windowsMyKeyStore.load(null, null);
// loading keymanager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(windowsMyKeyStore, null);
// building truststore
TrustManager[] trustAllManager = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllManager, new SecureRandom());
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1.2", "TLSv1.1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
HttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
HttpGet get = new HttpGet(...);
Проблема возникает из-за того, что Java выбирает первый сертификат (неправильный), который соответствует CertificateRequest с сервера, как можно увидеть в этом фрагменте, когда -Djavax.net.debug=all
:
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
matching alias: <<alias for SIGNING certificate>>
matching alias: <<alias for AUTHENTICATION certificate>>
*** Certificate chain
chain [0] = [
<< SIGNING certificate >>
]
Можно ли настроить Java так, чтобы он использовал правильный сертификат?