Проверка подлинности клиентского сервера с использованием самозаверяющего сертификата - Curl работает, но Apache HttpClient выдает исключение
Я пытаюсь реализовать аутентификацию клиента и сервера с помощью Apache HTTPClient и проверить ее с помощью самозаверяющего сертификата. Я попытался следовать нескольким учебникам и ответам на подобные вопросы здесь, но безуспешно. Я постарался максимально подробно описать все шаги, которые я делал, надеюсь, кто-то укажет, что я делаю неправильно:
Создал файл
req.conf
для конфигурации[req] prompt=no distinguished_name = req_distinguished_name [ req_distinguished_name ] O=selfSignedO CN=selfSignedCn DC=selfSignedDc
Сгенерированный серверный закрытый ключ и самозаверяющий сертификат
openssl req \ -config req.conf \ -x509 \ -newkey rsa:4096 \ -keyout server/server-private-key.pem \ -out server/server.crt \ -days 3650 \ -nodes
Создано хранилище ключей PKCS12, содержащее закрытый ключ и сертификат, созданный на предыдущем шаге
openssl pkcs12 \ -export \ -out server/server-key-store.p12 \ -inkey server/server-private-key.pem \ -in server/server.crt
скажем, пароль, который я использовал, был
123456
Сгенерировал закрытый ключ клиента и запрос на подпись сертификата.
openssl req \ -config req.conf \ -new \ -newkey rsa:4096 \ -out client/client-request.csr \ -keyout client/client-private-key.pem \ -nodes
Подписал запрос на подпись сертификата клиента с помощью закрытого ключа и сертификата сервера
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
Создано хранилище ключей 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
как пароль снова.Сгенерированное доверенное хранилище сервера, содержащее подписанный сертификат клиента
keytool \ -import \ -trustcacerts \ -alias root \ -file client/client-signed-cert.crt \ -keystore server/server-trust-store.jks
пароль?
123456
Керл работает, но только с
-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.
Настроил 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)