2015-09-29 3 views
2

tl; dr: Использование пользовательского CA без добавления его в постоянное хранилище ключей.Загрузить корневой сертификат CA во время выполнения в Java

Я пишу приложение Java, которое должно подключаться к удаленному серверу с помощью HTTPS. Код для подключения готов, однако SSL-сертификат сервера был подписан StartSSL, который не находится в корневом хранилище сертификатов CA.

Использование this code, я получаю достоверную информацию сертификата из веб-сайтов, как https://www.google.com/:

Response Code : 200 
Cipher Suite : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 

Cert Type : X.509 
Cert Hash Code : -1643391404 
Cert Public Key Algorithm : RSA 
Cert Public Key Format : X.509 

Cert Type : X.509 
Cert Hash Code : 771393018 
Cert Public Key Algorithm : RSA 
Cert Public Key Format : X.509 

Cert Type : X.509 
Cert Hash Code : 349192256 
Cert Public Key Algorithm : RSA 
Cert Public Key Format : X.509 

Тот же самый код бросает SSLHandshakeException для моего домена (назовем его https://www.example.com/).

Конечно, я мог бы вручную добавить сертификат в хранилище ключей, используя keytool (возможно, даже с Runtime.exec("keytool ...")), но это путь к загрязнению. Теперь я планирую добавить корневой сертификат StartSSL в свои файлы приложений для распространения, а затем загрузить его во временное хранилище ключей во время выполнения. Таким образом, «реальное» хранилище остается нетронутым.

Из того, что я прочел here и here, мне придется общаться с некоторыми классами, такими как TrustManager. Я даже нашел способ для completely turn off the validation, но это не то, что я хочу, поскольку он, кажется, устраняет всю цель зашифрованной связи.

Я даже нашел несколько строк кода, которые, кажется, делать именно то, что я хочу, но я не могу понять, как назвать этот метод т.е. какие значения для передачи в качестве аргументов:

public class SSLClasspathTrustStoreLoader { 
    public static void setTrustStore(String trustStore, String password) throws Exception { 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 
     KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); 
     InputStream keystoreStream = SSLClasspathTrustStoreLoader.class.getResourceAsStream(trustStore); 
     keystore.load(keystoreStream, password.toCharArray()); 
     trustManagerFactory.init(keystore); 
     TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 
     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, trustManagers, null); 
     SSLContext.setDefault(sc); 
    } 
} 

Кто-нибудь был в аналогичная ситуация раньше? Я буду признателен за любые советы о том, как справиться с этой проблемой. Если бы вы могли даже помочь мне получить код выше, я был бы действительно счастлив!

ответ

2

Вам необходимо будет создать пользовательскую TrustStore, как вы уже нашли. В дополнение к этому вам нужно будет создать собственную фабрику сокетов SSL, которая использует специализированный ящик доверия, о котором вы упомянули, и зарегистрировать его с помощью используемой инфраструктуры HTTP. Детали действительно зависят от структуры вашего выбора.

Нет ничего плохого в добавлении сертификата в хранилище ключей по умолчанию с использованием keytool. Вы можете обнаружить, что требуется больше одного сертификата. Если это так, вы должны убедиться, что все Java-приложение использует тот же магазин ключей, что и единственный источник правды. Это может стать очень волосатым, если вы используете несколько хранилищ ключей в одном приложении.

Надеюсь, это поможет.

+0

Что касается 'keytool' части вашего ответа: приложение будет распространяться на несколько клиентских систем. Изменение системы в хранилище ключей вручную невозможно для каждой отдельной системы и ее модификации во время выполнения сложно, так как пользователь может изменить пароль (который по умолчанию является «changeit», поэтому кто-то действительно может это сделать). В этом случае соединение не будет работать, или мне нужно будет запросить пароль, который не является удобным для пользователя imho.Но спасибо за ваш ответ, я дам ему еще один выстрел в ближайшее время. – Hexaholic

+0

Вы можете создать пользовательскую среду хранения ключей, если она не существует, или вы можете упаковать хранилище ключей с вашим приложением. Я не знаю деталей вашего проекта, но должно быть более элегантное решение. Удачи в любом случае :) – Boris

0

Это сработало для меня!

public static void setTrustStore(String trustStore, String password) throws Exception { 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 
     KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); 
     InputStream keystoreStream = SSLClasspathTrustStoreLoader.class.getResourceAsStream(trustStore); 
     keystore.load(keystoreStream, password.toCharArray()); 
     trustManagerFactory.init(keystore); 
     TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 
     SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, trustManagers, null); 
     SSLContext.setDefault(sc); 
    } 

ИЛИ Другой вариант заключается в использовании «portecle-1.9»

1.1 – Baixar o programa “portecle-1.9”. 
1.1.1 https://sourceforge.net/projects/portecle 

1.2 - Acessar a pasta security do JDK que será utilizado para rodar a aplicação 
1.2.1 Exemplo: C:\Program Files\Java\jdk1.7.0_67\jre\lib\security 
1.2.2 Fazer backup do arquivo “cacerts” (Só por segurança) 

1.3 - Abrir o programa portecle “portecle.jar” 
1.3.1 Acessar o “Menu > File > Open Keystore File..” 
1.3.2 Selecione o arquivo “cacerts” mande abrir 
1.3.3 Irá pedir senha, a senha padrão quando instala o JDK é “changeit” 
1.3.4 O programa irá listar os diversos certificados contidos no “cecerts” 
1.3.5 Acessar o “Menu > Tools > Import Trusted Certificate…” 
1.3.6 Selecione o arquivo de certificado “.pem“ ou “.cer” ou alguma outra extensão compatível. 
1.3.7 Será questionado se realmente o arquivo é “trusted” ou seja “confiável” . Aceita como confiavel. 
1.3.8 Também será possível alterar o “alias”, provavelmente não será necessário mudar então apenas aceites todas as opções até que receba a mensagem “Certificado importado”. 
1.3.9 Clique em “Salvar”, pois se não salvar as alterações não terão efeito! 
Смежные вопросы