Проверка подлинности клиентского сервера с использованием самозаверяющего сертификата - Curl работает, но Apache HttpClient выдает исключение

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

  1. Создал файл req.conf для конфигурации

    [req]
    prompt=no
    distinguished_name = req_distinguished_name
    
    [ req_distinguished_name ]
    O=selfSignedO
    CN=selfSignedCn
    DC=selfSignedDc
    
  2. Сгенерированный серверный закрытый ключ и самозаверяющий сертификат

    openssl req \
     -config req.conf \
     -x509 \
     -newkey rsa:4096 \
     -keyout server/server-private-key.pem \
     -out server/server.crt \
     -days 3650 \
     -nodes 
    
  3. Создано хранилище ключей PKCS12, содержащее закрытый ключ и сертификат, созданный на предыдущем шаге

     openssl pkcs12 \
     -export \
     -out server/server-key-store.p12 \
     -inkey server/server-private-key.pem \
     -in server/server.crt
    

    скажем, пароль, который я использовал, был 123456

  4. Сгенерировал закрытый ключ клиента и запрос на подпись сертификата.

    openssl req \
     -config req.conf \
     -new \
     -newkey rsa:4096 \
     -out client/client-request.csr \
     -keyout client/client-private-key.pem \
     -nodes
    
  5. Подписал запрос на подпись сертификата клиента с помощью закрытого ключа и сертификата сервера

    openssl x509 \
     -req \
     -days 360 \
     -in client/client-request.csr \
     -CA server/server.crt \
     -CAkey server/server-private-key.pem \
     -CAcreateserial \
     -out client/client-signed-cert.crt \
     -sha256
    
  6. Создано хранилище ключей PKCS12, содержащее закрытый ключ клиента и сертификат сертификата, созданный на предыдущем шаге.

     openssl pkcs12 \
      -export \
      -out client/client-keystore.p12 \
      -inkey client/client-private-key.pem \
      -in client/client-signed-cert.crt \
      -certfile server/server.crt
    

    мы использовали 123456 как пароль снова.

  7. Сгенерированное доверенное хранилище сервера, содержащее подписанный сертификат клиента

    keytool \
     -import \
     -trustcacerts \
     -alias root \
     -file client/client-signed-cert.crt \
     -keystore server/server-trust-store.jks
    

    пароль? 123456

  8. Керл работает, но только с -k

    curl -k \
       --cert client/client-signed-cert.crt \
       --key client/client-private-key.pem \
       https://localhost:443:/my/endpoint
    

    без -k Я получаю ошибку:

    curl: (60) SSL certificate problem: self signed certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
    curl performs SSL certificate verification by default, using a "bundle"
     of Certificate Authority (CA) public keys (CA certs). If the default
     bundle file isn't adequate, you can specify an alternate file
     using the --cacert option.
    If this HTTPS server uses a certificate signed by a CA represented in
     the bundle, the certificate verification probably failed due to a
     problem with the certificate (it might be expired, or the name might
     not match the domain name in the URL).
    If you'd like to turn off curl's verification of the certificate, use
     the -k (or --insecure) option.
    HTTPS-proxy has similar options --proxy-cacert and --proxy-insecure.
    
  9. Настроил Apache HTTPClient:

    private HttpClient createClient() throws Exception {
        String keyPassword = "123456";
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(resourceAsStream("/client/client-key-store.p12"), keyPassword.toCharArray());
        SSLContext sslContext = new SSLContextBuilder()
            .setProtocol("TLSv1.2")
            .loadKeyMaterial(ks, keyPassword.toCharArray())
            .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            .build()
        return HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();
    }
    

    (Конструкция выполняется несколькими способами, которые я здесь сжал, поэтому, если что-то странное или отсутствует, пожалуйста, дайте мне знать, возможно, я что-то скопировал.)

но при попытке отправить тот же запрос, что и в Curl, я получаю:

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135)
    at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1779)
    at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:124)
    at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1156)
    at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1266)
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1178)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:348)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:394)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)

0 ответов

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