Как я могу использовать аутентификацию сертификата с HttpsURLConnection?

Я пытаюсь подключиться к URL-адресу HTTPS, но мне нужно использовать аутентификацию клиента с сертификатом, размещенным в моей системе сторонним программным обеспечением.

Я не имею ни малейшего представления о том, как я должен его находить или использовать, и все, что мне нужно, - это пример кода C #, который значительно отличается от всех ответов Java, которые я нашел по этому поводу. (например, KeyStore нужен какой-то пароль, очевидно?)

Это пример кода C # у меня есть

System.Security.Cryptography.X509Certificates.X509CertificateCollection SSC_Certs = 
    new System.Security.Cryptography.X509Certificates.X509CertificateCollection();

Microsoft.Web.Services2.Security.X509.X509CertificateStore WS2_store =
    Microsoft.Web.Services2.Security.X509.X509CertificateStore.CurrentUserStore(
    Microsoft.Web.Services2.Security.X509.X509CertificateStore.MyStore);

WS2_store.OpenRead();

Microsoft.Web.Services2.Security.X509.X509CertificateCollection WS2_store_Certs = WS2_store.Certificates;

И затем он просто перебирает WS2_store_Certs CertificateCollection и проверяет их все таким образом. Чуть дальше, он устанавливает сертификаты так:

HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url_string);
httpWebRequest.ClientCertificates = SSC_Certs;

Все это выглядит довольно логично, даже если я не знаю, как он находит сертификаты, но я до сих пор не смог найти Java-эквивалент этого.

ОБНОВИТЬ

Соединение, которое я устанавливаю, является частью более крупного приложения, которое зависит от JDK 5, но мне удалось просто использовать банку sunmscapi, чтобы найти сертификат, который я ищу. Однако при попытке подключиться с использованием хранилища ключей Windows возникают ошибки, поэтому я решил, что обошёл проблему, получив нужный мне сертификат из хранилища Windows и вставив его в стандартный java. Теперь я получаю EOFException, за которым следует SSLHandshakeException, говорящее «Удаленное соединение закрыто во время рукопожатия». Трассировка отладки ssl не выявляет мне немедленной проблемы, так как нужный мне сертификат отображается здесь в цепочке сертификатов.

Он выполняет всю функцию ClientKeyExchange, говорит, что он завершен, а затем последние сообщения, которые я получаю из журнала отладки сразу после этого,

[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C D3 E1 E7 3D   C2 37 2F 41 F9 38 26 CC  .......=.7/A.8&.
Padded plaintext before ENCRYPTION:  len = 32
0000: 14 00 00 0C D3 E1 E7 3D   C2 37 2F 41 F9 38 26 CC  .......=.7/A.8&.
0010: CB 10 05 A1 3D C3 13 1C   EC 39 ED 93 79 9E 4D B0  ....=....9..y.M.
AWT-EventQueue-1, WRITE: TLSv1 Handshake, length = 32
[Raw write]: length = 37
0000: 16 03 01 00 20 06 B1 D8   8F 9B 70 92 F4 AD 0D 91  .... .....p.....
0010: 25 9C 7D 3E 65 C1 8C A7   F7 DA 09 C0 84 FF F4 4A  %..>e..........J
0020: CE FD 4D 65 8D                                     ..Me.
AWT-EventQueue-1, received EOFException: error

и код, который я использую для установки соединения

KeyStore jks = KeyStore.getInstance(KeyStore.getDefaultType());
jks.load(null, null);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
jks.setCertificateEntry("alias", cert1); //X509Certificate obtained from windows keystore
kmf.init(jks, new char[0]);

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null);

sslsocketfactory = sslContext.getSocketFactory();
System.setProperty("https.proxyHost", proxyurl);
System.setProperty("https.proxyPort", proxyport);

Authenticator.setDefault(new MyAuthenticator("proxyID", "proxyPassword"));
URL url = new URL(null, urlStr, new sun.net.www.protocol.https.Handler());
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
uc.setSSLSocketFactory(sslsocketfactory);
uc.setAllowUserInteraction(true);
uc.setRequestMethod("POST");
uc.connect();

(Я еще не пробовал HttpClient, потому что не знаю, как найти файл сертификата, и я также не уверен, будет ли он всегда одинаковым в каждой клиентской системе.)

ДРУГОЕ ОБНОВЛЕНИЕ

Я нашел CA для нужного мне сертификата в хранилище ключей WINDOWS-ROOT (и проверил с помощью .verify (), чтобы убедиться, что они все проверяют), я также добавил их в хранилище ключей java, но ничего не изменилось. Я предполагаю, что они должны пойти в TrustStore, но мне еще предстоит найти способ сделать это программно. (Я бы предпочел не полагаться на то, что конечные пользователи будут делать подобные вещи, поскольку все, что я могу от них гарантировать, это то, что сертификат и центры сертификации будут присутствовать из-за стороннего программного обеспечения, упомянутого в начале этого нелепо длинного вопроса.)

ЕЩЕ БОЛЬШЕ ОБНОВЛЕНИЙ

Добавляя предыдущее обновление, я пришел к выводу, что моя проблема должна заключаться в том, что мои CA не находятся в файле cacerts Java, поэтому он получает список доверенных CA с сервера, но не распознает их и впоследствии не отправляет обратно ни одного сертификата, что вызывает сбой соединения. Таким образом, проблема остается: как заставить Java использовать хранилище ключей в качестве хранилища доверенных сертификатов или программно добавлять сертификаты в хранилища (без необходимости указывать пути к файлам)? Потому что, если это невозможно, это оставляет мне секретный вариант C,шаман, Я начну колоть куклу Герцога иглами, на всякий случай.

Ответы на вопрос(3)

Ваш ответ на вопрос