Извиняюсь заранее, я все еще довольно новичок в кодировании для SSL.Я искал ответы в течение последних нескольких дней, и хотя я нашел много предложений, пока ничего не получалось.
У меня есть сервер, реализованный поверх Dropwizard, который нужно принять.входящее HTTPS-соединение и использовать прикрепленный сертификат для однозначной идентификации клиента.В настоящее время я использую все самозаверяющие сертификаты в процессе разработки.Пара сертификатов сервера была создана с использованием пары цепочка - корневая пара -> промежуточная пара -> пара серверов.P12 сервера был создан с использованием объединения промежуточного и серверного сертификатов, а также закрытого ключа сервера.Затем он был добавлен в пустой JKS и стал хранилищем ключей сервера.
Отдельно я создал два клиентских сертификата, один из которых использовал ту же промежуточную пару в качестве базы, а другой - как чистую пару автономных сертификатов.Часть открытого ключа x509 обеих этих пар сертификатов была добавлена в файл JKS и стала TrustStore сервера.Конфигурация Dropwizard выглядит следующим образом:
type: "https"
port: "9843"
keyStorePath: "keystore.jks"
keyStorePassword: "changeme"
keyStoreType: "JKS"
trustStorePath: "truststore.jks"
trustStorePassword: "changeme"
trustStoreType: "JKS"
allowRenegotiation: false
validateCerts: false
validatePeers: false
needClientAuth: true
wantClientAuth: true
Я могу подключиться к серверу, используя curl
и любую из пар сертификатов клиента:
curl -v --cert client.pem --key client.key -k https://localhost:9843/v1/ld
При включенной отладке SSL сервер регистрирует журналследующее:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<CN=*.me.com, O=Me, ST=Massachusetts, C=US>
<O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US>
*** ServerHelloDone
dw-51, WRITE: TLSv1.2 Handshake, length = 3536
dw-44, READ: TLSv1.2 Handshake, length = 1047
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: O=Internet Widgits Pty Ltd, L=North Reading, ST=Massachusetts, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: 23250299629324311533731283912176366463399376328149948822580485256237233115567136794461732268017120297060017586981907979910958857247642884566364833267711927344361604478514119965230314679194017013023991389216461419030751049820266939279047536006291610734616600760688907006770883510297954698233112783686968024400749969025850008781641616624298935923926427096257861170476293580684942956111432790304698635393966967864288730561678135798437678912431564767611000006312358137647455886578135011989168265295083928014176435879778838966450081419161406209555593636745048857672445188811541416453143809594265089422302064600885289819601
public exponent: 65537
Validity: [From: Wed Dec 05 13:52:49 EST 2018,
To: Thu Dec 05 13:52:49 EST 2019]
Issuer: O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US
SerialNumber: [ 8174655c c8387da4]
Certificate Extensions: 3
...
Пока все хорошо.Затем я пытаюсь подключиться к своему серверу, используя клиент Java, используя ту же пару сертификатов, объединенную в один файл P12.Код Java выглядит следующим образом:
char[] password = "changeme".toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (FileInputStream fileInputStream = new FileInputStream("client.p12")) {
keystore.load(fileInputStream, password);
}
SSLContext sslContext =
SSLContexts.custom()
.loadKeyMaterial(keystore, password)
.loadTrustMaterial(null, (chain, authType) -> true)
.build();
return HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
Но когда этот клиент пытается подключиться к серверу, регистрируется следующее:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<CN=*.me.com, O=Me, ST=Massachusetts, C=US>
<O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
Я также попытался использовать SSLConnectionSocketFactory
, инициализированный с помощью sslContext, иRegistry<ConnectionSocketFactory>
регистрация socketFactory для "https".Ничего не сработало.Я совершенно не знаю, почему curl
принимает полномочия по сертификации и отправляет сертификат клиента, а httpClient java - нет.
РЕДАКТИРОВАТЬ:
Я пытался добавить публичный сертификат сервера взапрос клиента, это не имело значения - я все еще вижу то же самое поведение.Код был обновлен следующим образом:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
try (FileInputStream fileInputStream = new FileInputStream("server.cert.pem")) {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(IOUtils.toByteArray(fileInputStream))) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(byteArrayInputStream);
trustStore.setCertificateEntry("server", certificate);
}
}
SSLContext sslContext =
SSLContexts.custom()
.loadKeyMaterial(keystore, password)
.loadTrustMaterial(trustStore, (chain, authType) -> true)
.build();