Проверяющий сервер выдает сертификаты Verisign Исключение сертификата недоверенного сервера

У меня проблема с проверкой сертификата Verisign при попытке соединения с HttpsURLConnection с нашим бэкэндом.

Текущая цепочка сертификации:$openssl s_client -connect host:443

0 s:/C=AT/ST=xxx/L=xxx/O=xxx/CN=host
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3

1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth
ority - G5

2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth
ority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

3 s:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

Я почти уверен, что скачал и добавил все сертификаты в KeyStore, но я все еще получаю исключение: "javax.net.ssl.SSLException: не доверенный сертификат сервера", и причина в том, что java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor found but certificate validation failed.

Мой код для получения соединения:

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("verisign_0", getVerisign0());
keyStore.setCertificateEntry("verisign_1", getVerisign1());
keyStore.setCertificateEntry("verisign_2", getVerisign2());
keyStore.setCertificateEntry("verisign_3", getVerisign3());

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
return urlConnection;

проблема происходит, когда connection.connect() называется. Все методы getVerisign() возвращают правильные сертификаты. Есть ли шаг, который я забыл? Может быть, особый порядок, в котором сертификаты должны быть добавлены?

Просто чтобы уточнить, я использовал именно эту технику с сертификатами swisssign, и она сработала. Я сталкиваюсь с этой проблемой, потому что некоторые устройства Android 2.1, 2.2 не имеют корневых сертификатов. Заранее спасибо.

Трассировки стека:

[0] = {java.lang.StackTraceElement@830078967208}"org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)"
[1] = {java.lang.StackTraceElement@830078967584}"org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)"
[2] = {java.lang.StackTraceElement@830078967960}"org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)"
[3] = {java.lang.StackTraceElement@830078968368}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)"
[4] = {java.lang.StackTraceElement@830078968816}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:147)"

2 ответа

Решение

Без дальнейшего кода я не могу сказать, но я вижу, что вы загружаете доверенные сертификаты, но где вы загружаете свой собственный Keystore? Если это в другом коде, я не могу сказать.

Также, что происходит, когда вы пытаетесь использовать внешний Truststore, например, $JAVA_HOME/jre/lib/security/cacerts

Предполагая, что вы действительно хотите использовать динамическое хранилище доверия (обычно они довольно статичны), взгляните на

http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/

Как было сказано ранее, хранилище TrustStore внутри JVM является статическим, после инициализации сертификаты не могут быть добавлены к нему (как я заметил с аналогичной проблемой). Простым решением является добавление ваших сертификатов к сертификату по умолчанию: $JAVA_HOME/jre/lib/security/cacerts

Или попробуйте включить код инициализации TrustStore в статический блок {}, чтобы быстрее его инициализировать и получить возможность обойти поведение по умолчанию.

Вы также можете использовать пользовательский файл KeysStore и попросить jvm использовать его с параметрами -Djavax.net.ssl.keyStore*.

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