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

Я пытаюсь реализовать аутентификацию клиента и сервера с помощью 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...