клиент веб-сервиса - с хранилищем ключей - PullRequest
0 голосов
/ 15 октября 2019

Мне нужно создать клиент веб-службы с хранилищем ключей. Но это ошибка:

sun.security.provider.certpath.SunCertPathBuilderException: невозможно найти допустимый путь сертификации для запрошенной цели

Мой код:

private SSLSocketFactory getFactory() throws Exception {

          File pKeyFile = new ClassPathResource("jks/dex-client-issuer-wss.jks").getFile();

          KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
          KeyStore keyStore = KeyStore.getInstance("JKS");

          InputStream keyInput = new FileInputStream(pKeyFile);
          keyStore.load(keyInput, pass.toCharArray());
          keyInput.close();

          keyManagerFactory.init(keyStore, pass.toCharArray());

          SSLContext context = SSLContext.getInstance("TLS");
          context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

          return context.getSocketFactory();
    }

это http-связь:

URL url = new URL("https://dexxis-demo1.gemalto.com/DEX/communication/issuer-interface");
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setSSLSocketFactory(getFactory());

У меня есть только файл dex-client-isser-wss.jks, который работает с мылом, как я могу создать соединение с этим файлом сертификата

1 Ответ

2 голосов
/ 16 октября 2019

«невозможно найти действительный путь сертификации» (во время рукопожатия SSL / TLS) не имеет никакого отношения к вашему хранилищу ключей - это означает, что сертификат server не проверяется по вашему хранилищу доверенных сертификатов , так как вы передали null в качестве 2-го аргумента context.init, это значение по умолчанию для JRE, то есть файл, указанный в sysprop javax.net.ssl.trustStore, если установлено иначе JRE/lib/security/cacerts (или .../jssecacerts, если он существует).

На этом сервере используется сертификат, выданный под корневым сертификатом Gemalto Business Root Certificate Authority, который не включен в cacerts, поставляемые с пакетами Oracle Java, или в любые другие известные доверенные хранилища, которые я знаю, и не известен в общедоступных журналах прозрачности(согласно https://crt.sh). SoapUI, предположительно потому, что он разработан как инструмент разработки, тестирования и отладки, игнорирует недействительные или подозрительные сертификаты, но браузер или curl или wget по этому URL-адресу не должен работать, если только хранилище доверенных сертификатов (s) в вашей (ых) системе (ах) были внесены изменения или они необычны. OTOH openssl s_client, который также в основном является средством отладки сообщает об ошибке, но в любом случае устанавливает соединение.

Если вывы все равно хотите доверять этому CA, одному из его (двух) промежуточных звеньев или сайту, что вам необходимо иметь соответствующий сертификат в доверенном хранилище. обычная практика - доверять корневому сертификату CA, ноJava поддерживает использование любого сертификата в цепочке, включая сертификат EE, в качестве привязки. Поскольку вы уже создаете свой собственный контекст и менеджер ключей,с тем же успехом вы можете создать свой собственный менеджер доверия, а не изменять JRE по умолчанию, который (как правило) зависит от платформы / среды, а иногда и сложен. Вы можете получить нужный сертификат и поместить его в отдельный файл хранилища ключей (см. Ниже), загрузить его и использовать для создания менеджера доверия. Или, так как у вас уже есть файл хранилища ключей для вашего собственного ключа + сертификаты, Java поддерживает наличие в одном файле и записи privateKey или записей и для доверенного участника или записей для другой стороны / сторон, поэтомуВы можете просто добавить их сертификат к существующему JKS и использовать тот же KeyStore объект в TrustManagerFactory, как и в KeyManagerFactory, чтобы создать массив trustmanager для вашего контекста.

Простые способы получитьсертификаты:

  • openssl s_client -showcerts -connect host:port </dev/null (в Windows <NUL:) - с портом 443;в настоящее время многие серверы нуждаются в расширении индикации имени сервера (он же SNI), и для OpenSSL ниже 1.1.1 вы должны добавить -servername host, чтобы предоставить его, но этот сервер не делает. Это выводит блок PEM для каждого сертификата с сервера с метками перед каждым показом s: (subjectname) и i: (issuername). Обратите внимание, что после первого сертификата, который является обязательным сертификатом EE, этот сервер отправляет сертификаты CA в порядке сверху вниз, а не снизу вверх. Технически это является нарушением RFC 5246 (или ранее 4346 или 2246);RFC 8446 для TLS1.3 разрешает это, потому что это уже было распространенное расширение, и Java JSSE, в частности, поддерживает его.

  • keytool -printcert -rfc -sslserver host - также поддерживает host:port, но по умолчанию443, что хорошо для вас. При этом выводятся только блоки PEM, поэтому, если вы еще не знали из моего предыдущего элемента о порядке, вам нужно будет декодировать каждый из них, чтобы выяснить, что есть, или просто экспериментировать, пока вы не найдете правильный.

В любом случае возьмите нужный блок PEM и поместите его в файл, и выполните команду

keytool -importcert -keystore jksfile -alias somealias -file thecertfile

somealias, равную , требуется , чтобы быть уникальнымвнутри файла (что тривиально, если вы поместите его в свой собственный файл) и нечувствителен к регистру (условно строчные буквы), но должен быть описательным или мнемоническим, и буквенно-цифровым, только если это возможно. Затем используйте полученный файл, как указано выше.

...