Ответ 1
Вам нужно добавить корневой сертификат в хранилище ключей.
Я пытаюсь установить соединение SSL Socket (и делаю следующее на клиенте)
Я создаю запрос подписи сертификата, чтобы получить подписанный сертификат клиента
Теперь у меня есть закрытый ключ (используемый во время CSR), подписанный клиентский сертификат и корневой сертификат (полученный вне диапазона).
Я добавляю закрытый ключ и подписанный сертификат клиента в цепочку сертификатов и добавляю его в диспетчер ключей. и корневой сертификат доверенному менеджеру. Но я получаю неправильную ошибку сертификата.
Я уверен, что использую правильные сертификаты. Должен ли я добавить подписанный клиентский сертификат к менеджеру доверия? Пробовал это, не повезло.
//I add the private key and the client cert to KeyStore ks
FileInputStream certificateStream = new FileInputStream(clientCertFile);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
java.security.cert.Certificate[] chain = {};
chain = certificateFactory.generateCertificates(certificateStream).toArray(chain);
certificateStream.close();
String privateKeyEntryPassword = "123";
ks.setEntry("abc", new KeyStore.PrivateKeyEntry(privateKey, chain),
new KeyStore.PasswordProtection(privateKeyEntryPassword.toCharArray()));
//Add the root certificate to keystore jks
FileInputStream is = new FileInputStream(new File(filename));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
java.security.cert.X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
System.out.println("Certificate Information: ");
System.out.println(cert.getSubjectDN().toString());
jks.setCertificateEntry(cert.getSubjectDN().toString(), cert);
//Initialize the keymanager and trustmanager and add them to the SSL context
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "123".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(jks);
Существует ли какая-то цепочка сертификатов, которую мне нужно создать здесь?
У меня также был p12 с этими компонентами, и, используя довольно похожий код, добавляя закрытый ключ к keymanager и корневому сертификату от p12 в менеджер доверия, я мог бы заставить его работать. Но теперь мне нужно заставить его работать без p12.
EDIT: запрошена трассировка стека. Надеюсь, этого будет достаточно. (ПРИМЕЧАНИЕ: Я замаскировал имена файлов)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
at client.abc2.openSocketConnection(abc2.java:33)
at client.abc1.runClient(abc1.java:63)
at screens.app.abc.validateLogin(abc.java:197)
... 32 more
Вам нужно добавить корневой сертификат в хранилище ключей.
Если сертификат сервера подписан и действителен, вам нужно только открыть соединение, как обычно:
import java.net.*;
import java.io.*;
public class URLConnectionReader {
public static void main(String[] args) throws Exception {
URL google = new URL("https://www.google.com/");
URLConnection yc = google.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
Обратите внимание, что URL-адрес имеет схему HTTPS, указывающую использование SSL.
Если сертификат сервера подписан, но вы используете другой IP-адрес/доменное имя, чем тот, что указан в сертификате, вы можете обойти проверку имени узла с помощью этого:
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName,SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Если сертификат не подписан, вам необходимо добавить его в хранилище ключей, используемое JVM (полезные команды).
Я получил эту ошибку, когда удалил эти 2 строки. Если вы знаете, что у вашего хранилища ключей есть правильные сертификаты, убедитесь, что ваш код смотрит в правильное хранилище ключей.
System.setProperty("javax.net.ssl.keyStore", <keystorePath>));
System.setProperty("javax.net.ssl.keyStorePassword",<keystorePassword>));
Мне также нужен этот аргумент VM:
-Djavax.net.ssl.trustStore=/app/certs/keystore.jk
Подробнее см. Здесь:
fooobar.com/info/404791/...