Пост-запрос HttpClient с проверкой подлинности сертификата клиента

Немного предыстории:

Я пытаюсь отправить файлы результатов теста в eVpT. Это делается через GKV-сервер: https://verarbeitung.gkv-kommunikationsserver.de/meldung/extra14.meldung

У нас есть аналогичная настройка для производственного аналога, и она отправляет на тот же сервер GKV.

К проблеме:

Сначала я сгенерировал пару ключей, примерно так:

keytool -genkeypair -v -alias "TEST" -validity 1095 -keyalg RSA -sigalg SHA256withRSA -keysize 2048 -keystore TEST.keystore -dname "CN=NAME, OU=BN1234, OU=COMPANY NAME, O=ITSG TrustCenter fuer Arbeitgeber, C=DE"

Получив файл хранилища ключей, я создал запрос сертификата:

keytool -certreq -alias "TEST" -file TEST.p10 -sigalg SHA256withRSA -keystore TEST.keystore

Это было отправлено на сервер GKV для подписи, и обратно пришёл файл.p7c, который я импортировал в вышеупомянутый файл хранилища ключей:

keytool -import -keystore TEST.keystore -alias TEST -trustcacerts -file TEST.p7c

Тип хранилища ключей - JKS, если это имеет значение.

Настройка для запроса следующая:

public HttpResponse send(String request, String serverUrl, boolean isEvptTest) {
    HttpClient httpClient = new HttpClient();
    return httpClient.post(request, serverUrl, new HttpClient.HttpPostCallback() {
        @Override
        public void configure(DefaultHttpClient defaultHttpClient, HttpPost httpPost) {
            try {
                httpPost.setHeader("Content-Type", "application/octet-stream");
                registerHttpsScheme(defaultHttpClient);
                addProxy(defaultHttpClient);
            } catch (Exception e) {
                throw new RuntimeException("could not register https scheme", e);
            }
        }
    });
}

private void addProxy(DefaultHttpClient httpClient) {
    String proxyHost = System.getProperty(Constants.HTTP_PROXY_HOST_PROPERTY);
    if (!Util.isEmpty(proxyHost)) {
        String proxyPort = System.getProperty(Constants.HTTP_PROXY_PORT_PROPERTY);
        HttpHost proxy = new HttpHost(proxyHost, Integer.parseInt(proxyPort), "http");
        httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
        log.debug(String.format("added proxy host %s port %s", proxyHost, proxyPort));
    }
}

private void registerHttpsScheme(DefaultHttpClient httpClient) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    SSLSocketFactory socketFactory = new SSLSocketFactory(testKeyStore, testKeyStoreService.getKeyStorePassword(), trustStore);
    port = 443;
    Scheme sch = new Scheme("https", port, socketFactory);
    httpClient.getConnectionManager().getSchemeRegistry().register(sch);
}

Метод отправки в HttpClient:

public HttpResponse post(String content, String url, HttpPostCallback callback) {
    DefaultHttpClient httpClient = null;
    org.apache.http.HttpResponse response = null;
    HttpResponse serverResponse = new HttpResponse();
    try {
        httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(content));

        if (callback != null) {
            callback.configure(httpClient, httpPost);
        }

        if (log.isDebugEnabled()) {
            log.debug(format("will post to url[%s] the following content[%s]", url, content));
            Header[] allHeaders = httpPost.getAllHeaders();
            for (Header header : allHeaders) {
                log.debug("header = " + header);
            }
        }

        response = httpClient.execute(httpPost);
        serverResponse.setStatusCode(response.getStatusLine().getStatusCode());
        log.debug(format("server response statuscode[%s]", serverResponse.getStatusCode()));
        String entity = EntityUtils.toString(response.getEntity());
        serverResponse.setResponse(entity);
        if (log.isDebugEnabled()) {
            log.debug(format("received response [%s]", entity));
        }
    } catch (Exception e) {
        log.error(format("error while sending to [%s]", url), e);
        serverResponse.setResponse(e.getMessage());
    } finally {
        consumeContent(httpClient, response);
    }
    return serverResponse;
}

это работает для обычных транзакций с сервером GKV, но когда я пытаюсь использовать тестовое хранилище ключей, я получаю ответ 403.


Я запустил мою программу с предложенным флагом javax.net.debug и получил следующее (если какая-то часть потребностей требует более подробной информации, пожалуйста, дайте мне знать):

found key for : *1234*
chain [0] = [
[
  Version: V3
  Subject: CN=*NAME*, OU=*BN1234*, OU=*COMPANY NAME*, O=ITSG TrustCenter fuer Arbeitgeber, C=DE
  Signature Algorithm: SHA256withRSA, OID = *SOMEID*
...

затем идет список всех доверяемых сертификатов, включая:

*.gkv-kommunikationsserver.de

Когда выполняется фактический запрос HTTP POST:

http-bio-8080-exec-4, setSoTimeout(0) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1484796190 bytes = { 224, 120, 124, 66, 118, 48, 83, 225, 119, 151, 135, 164, 71, 96, 51, 216, 132, 136, 223, 123, 66, 151, 254, 6, 198, 88, 86, 67 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
***

...

http-bio-8080-exec-4, READ: TLSv1.2 Handshake, length = 3043
*** ServerHello, TLSv1.2
RandomCookie:  GMT: 1484796191 bytes = { 74, 209, 14, 128, 123, 109, 178, 53, 206, 74, 209, 82, 66, 241, 252, 13, 234, 164, 2, 171, 46, 102, 203, 234, 224, 28, 213, 70 }
Session ID:  {154, 66, 0, 0, 252, 124, 28, 13, 62, 10, 104, 127, 66, 84, 189, 234, 174, 203, 170, 168, 194, 0, 146, 12, 98, 164, 135, 5, 176, 186, 95, 180}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***

...

*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: CN=*.gkv-kommunikationsserver.de, O=ITSG GmbH, OU=Systeme und Netze, L=Heusenstamm, ST=Hessen, C=DE
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

...

***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=*.gkv-kommunikationsserver.de, O=ITSG GmbH, OU=Systeme und Netze, L=Heusenstamm, ST=Hessen, C=DE
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

...

*** ECDH ServerKeyExchange
Signature Algorithm SHA1withRSA
Server key: Sun EC public key, 521 bits

...

*** ECDHClientKeyExchange
SESSION KEYGEN:
PreMaster Secret:
CONNECTION KEYGEN:
Client Nonce:
Server Nonce:
Master Secret:
Client MAC write Secret:
Server MAC write Secret:
Client write key:
Server write key:
... no IV derived for this protocol
http-bio-8080-exec-4, WRITE: TLSv1.2 Change Cipher Spec, length = 1

... Затем он начинает проверять данные, которые, кажется, идут очень хорошо. Затем по какой-то причине делается новый запрос Hello:

*** HelloRequest (empty)
%% Client cached [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]
%% Try resuming [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384] from port 62362
*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1484796208 bytes = { 130, 109, 91, 183, 192, 75, 115, 223, 4, 85, 231, 11, 50, 168, 37, 5, 25, 155, 187, 103, 246, 21, 104, 162, 129, 137, 11, 19 }
Session ID:  {154, 66, 0, 0, 252, 124, 28, 13, 62, 10, 104, 127, 66, 84, 189, 234, 174, 203, 170, 168, 194, 0, 146, 12, 98, 164, 135, 5, 176, 186, 95, 180}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension renegotiation_info, renegotiated_connection: 39:a7:89:65:54:45:31:c8:c1:bc:93:b0
***

...

*** ServerHello, TLSv1.2
RandomCookie:  GMT: 1484796208 bytes = { 104, 194, 244, 49, 210, 153, 252, 205, 241, 25, 177, 239, 212, 114, 206, 70, 186, 6, 152, 31, 243, 128, 145, 3, 86, 42, 208, 145 }
Session ID:  {158, 32, 0, 0, 233, 255, 55, 252, 77, 3, 17, 171, 9, 23, 239, 78, 0, 229, 23, 91, 244, 92, 163, 129, 33, 72, 196, 250, 199, 121, 51, 85}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: 39:a7:89:65:54:45:31:c8:c1:bc:93:b0:f1:24:0e:aa:fc:54:f3:7a:1a:79:26:8e
***

...

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withRSA, SHA512withECDSA, SHA256withRSA, SHA384withRSA, SHA1withRSA, SHA256withECDSA, SHA384withECDSA, SHA1withECDSA, SHA1withDSA
Cert Authorities:
<CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE>
<CN=StartCom Certification Authority, OU=Secure Digital Certificate Signing, O=StartCom Ltd., C=IL>
<CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US>
<OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US>
<CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE>
<CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE>
<CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US>
<O=Datenaustausch im Gesundheits- und Sozialwesen, C=DE>
<CN=Microsoft Root Certificate Authority 2011, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US>
<CN=Microsoft Root Authority, OU=Microsoft Corporation, OU=Copyright (c) 1997 Microsoft Corp.>
<CN=Microsoft Root Certificate Authority, DC=microsoft, DC=com>
[read] MD5 and SHA1 hashes:  len = 1336

...

*** ServerHelloDone
[read] MD5 and SHA1 hashes:  len = 4
0000: 0E 00 00 00                                        ....
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain

... Это только я, или это говорит мне, что мой сертификат клиента не был добавлен в хранилище доверенных сертификатов сервера?

1 ответ

Решение

Несколько вещей, чтобы попробовать:

  1. Является ли корень цепочки выдачи CA для вашего сертификата клиента в вашем хранилище доверия? Если нет, добавьте, что в противном случае он не будет согласовывать, откуда был выдан ваш сертификат, и не будет выбирать его.
  2. Вы можете запустить вашу программу с -Djavax.net.debug = all. Это сбросит метрическую... тонну информации на вашу консоль. Он покажет все сертификаты, загруженные как доверенные издатели, параметры квитирования, а также взаимодействие между сервером и клиентом при определении того, кто должен что-то предоставлять при обмене.

После продолжительного обсуждения мы дошли до корня проблемы. У Рикко было почти все необходимое, за исключением корневого сертификата цепочки выдачи в доверенном хранилище.

В механике рукопожатия TLS на сервере представлен список органов выдачи

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withRSA, SHA512withECDSA, SHA256withRSA, SHA384withRSA, SHA1withRSA, SHA256withECDSA, SHA384withECDSA, SHA1withECDSA, SHA1withDSA
Cert Authorities:
<CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE>
<CN=StartCom Certification Authority, OU=Secure Digital Certificate Signing, O=StartCom Ltd., C=IL>
<CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US>
<OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US>
<CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE>
<CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE>
<CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US>
<O=Datenaustausch im Gesundheits- und Sozialwesen, C=DE>
<CN=Microsoft Root Certificate Authority 2011, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US>
<CN=Microsoft Root Authority, OU=Microsoft Corporation, OU=Copyright (c) 1997 Microsoft Corp.>
<CN=Microsoft Root Certificate Authority, DC=microsoft, DC=com>

Механизм доверия попытается проверить, знает ли он об одном из этих органов выдачи по его присутствию в хранилище доверенных сертификатов. Как только это будет решено, он попытается найти первый privateKeyEntry в хранилище ключей, который имеет соответствующий сертификат в своей цепочке, а затем, если закрытый ключ может быть восстановлен, использовать этот сертификат для обеспечения второй половины аутентификации. См. RFC 5246 для подробностей протокольного рукопожатия.

После добавления сертификата, связанного с "", в хранилище доверенных сертификатов Ricco был успешным и преодолел ошибку 403, описанную в вопросе.

Также обратите внимание, что в этом случае сервер был настроен на "требовать", а не "требовать" проверку подлинности сертификата клиента. В режиме "хочу" клиентский сертификат будет представлен, если он есть, но в противном случае он будет работать в обычном режиме подключения TLS. В режиме "требуется" клиентский сертификат должен быть представлен для завершения соединения TLS.

Другие вопросы по тегам