Как поддерживать несколько TrustStores в клиентском приложении java SSL - PullRequest
7 голосов
/ 09 сентября 2010

В нашем java-приложении нам нужно общаться со списком серверов по SSL, используя протокол https.Список серверов для связи будет меняться во время выполнения.Изначально у нас нет ни одного сертификата сервера.Во время выполнения мы получим новый сертификат сервера и добавим сертификат открытого ключа в хранилище доверенных сертификатов;и любое новое https-соединение с сервером должно использовать обновленное хранилище доверенных сертификатов.

Мы думаем, что нам следует использовать два хранилища доверенных сертификатов: одно хранилище (по умолчанию поставляется с jre) и другое, содержащее сертификаты серверов, которыеДобавить / удалить динамически в списке.Это гарантирует, что мы не изменим TrustStore (cacerts) по умолчанию для Java.

Пожалуйста, предложите, как этого можно достичь.Кроме того, есть ли способ использовать определенное хранилище доверия только для определенного потока в java, так что другие (существующие и новые) потоки все еще должны использовать хранилище java trueststore (cacerts), и один конкретный поток будет использовать конкретное хранилище доверенных сертификатов длясервер.

Спасибо, Дипак

Ответы [ 2 ]

5 голосов
/ 09 сентября 2010

Если вы хотите импортировать сертификат динамически, вам может потребоваться использовать пользовательский x509TrustManager. Это делается при настройке SSLContext, который сам по себе используется для создания SSLSocketFactory или SSLEngine.

jSSLutils - это библиотека, которая позволяет обернуть существующие диспетчеры доверия и настроить определенные параметры. Вам это не нужно, но это может помочь.

Это будет выглядеть следующим образом:

PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
    @Override
    public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
        return new X509TrustManager() { 
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return origManager.getAcceptedIssuers();
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                try {
                    // This will call the default trust manager
                    // which will throw an exception if it doesn't know the certificate
                    origManager.checkServerTrusted(chain, authType);
                } catch (CertificateException e) {
                    // If it throws an exception, check what this exception is
                    // the server certificate is in chain[0], you could
                    // implement a callback to the user to accept/refuse
                }
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                origManager.checkClientTrusted(chain, authType);
            }
        };
    }
});
SSLContext sslContext = sslContextFactory.buildSSLContext();

((PKIX)SSLContextFactory и X509TrustManagerWrapper взяты из jSSLutils, но остальное доступно с J2SE / J2EE.)

Есть несколько CertificateException с , которые вы, возможно, захотите поймать (см. Подклассы). Если вы сделаете обратный вызов для пользователя, возможно, что соединение SSL / TLS в первый раз не будет выполнено из-за истечения времени ожидания при рукопожатии SSL / TLS (если обратный вызов занимает слишком много времени для ответа.)

Затем вы можете использовать это SSLContext в качестве значения по умолчанию, используя SSLContext.setSSLContext(...) (из Java 6), но это не всегда хорошая идея. Если можете, передайте SSLContext в библиотеку, которая устанавливает соединение SSL / TLS. Как это делается, может быть разным, но Apache HTTP Client 4.x, например, имеет несколько опций для настройки своих параметров SSL, один из которых - передача KeyStore s, другой - передача SSLContext.

.

Вы также можете использовать что-то для каждого потока, а не для каждого объекта, который будет подключаться (зависит от библиотеки), проверив текущий поток внутри X509TrustManager: это, вероятно, усложнит ситуацию с точки зрения синхронизации и управления потоками / «осведомленность» от доверительного управляющего.

2 голосов
/ 26 января 2013

Этот вопрос настолько стар, что я сомневаюсь, что мой бит поможет кому-нибудь, но здесь все идет ...

Если вы хотите решить проблему ОП (оригинальный постер), не прибегая к изменениям кода, вы можете настроитьваша JVM (я тестировал только с Tomcat) для поддержки желаемой конфигурации OP: 1. оставьте «упакованный» файл JDK cacerts в одиночку 2. импортируйте ваши сертификаты в отдельный файл и пусть ваши приложения JAVA «доверяют» им

Раньше я просто импортировал свой дополнительный сертификат в отдельный файл и затем ссылался на него при запуске JVM с параметром '-Djavax.net.ssl.trustStore = $ JAVA_HOME / jre / lib / security / jssecacerts' с большим успехом, но яУгадайте, что недавние (в некоторой степени) проблемы с безопасностью JAVA изменили автоматическое включение файла cacerts, распространяемого вместе с SDK.

Так что я нашел изящное решение, используя Intel из этого поста и этих страниц (с некоторыми незначительными изменениями):- http://www.coderanch.com/t/529157/Tomcat/Configure-Tomcat-trust-store-cacerts - http://andyarismendi.blogspot.com/2012/01/changing-tomcats-ca-trust-keystore-file.html

Что я делал раньше: - установите параметр JVM trustStore для моего отдельного файла хранилища ключей(в который я бы импортировал дополнительные сертификаты) следующим образом

Что я делаю сейчас: - Установите параметр trustStore в файл «упакованных» cacerts - Установите параметр keyStore в мой файл «дополнительных сертификатов» - Установите параметрПараметр keyStorePassword для пароля моего хранилища ключей (по умолчанию это changeit)

Как это выглядит:

-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts \
-Djavax.net.ssl.keyStore=$JAVA_HOME/jre/lib/security/jssecacerts \
-Djavax.net.ssl.keyStorePassword="changeit" \

Надеюсь, это кому-нибудь пригодится.Я не на 100% уверен, что вам нужно указывать пароль хранилища ключей, поскольку вы не используете trustStore, но он работает, когда вы это делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...