Como adicionar vários caminhos de armazenamento confiável a “java.net.ssl.trustStore”?

Eu quero o meu código Java para procurar o certificado de CA do servidor em um keystore … se ele é incapaz de encontrar o certificado específico (que eu acho que será conhecido apenas quando eu tento conectar via LDAP ao Directory Server), deve procure o certificado em outro keystore, cujo caminho eu conheço.

Eu tentei isso:

System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts" + System.getProperty("path.separator") + path/to/second/keystore);

Mas isso não parece funcionar.

Adicionar apenas um caminho (qualquer um deles) funciona, ou seja, ele é executado como charme se o certificado for encontrado e falhar se não for.

Então minha pergunta é:

  1. Existe um método para adicionar caminhos de keystore multpile a javax.net.ssl.trustStore?

  2. Se não for possível, como devo escrever meu código (estou pedindo o algoritmo) para que ele simplesmente não ative Exceção após a primeira pesquisa e falhe?

PS: Eu não estou muito familiarizado com o Java.

Abaixo está a seção relevante do meu código:

 if(useSSL) { try { SSLContext se = SSLContext.getInstance("TLS"); Security.addProvider(se.getProvider()); } catch(NoSuchAlgorithmException e) { } System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts"); com.org.ldap.LDAPSocketFactory ssf = new LDAPJSSESecureSocketFactory(); LDAPConnection.setSocketFactory(ssf); } try { lc = new LDAPConnection(); lc.connect( ldapServer, ldapPort); lc.bind( ldapVersion, ldapUser, (userInfo[1]).getBytes() ); } catch (LDAPException le) { le.printStackTrace(); } 

Você não pode ter vários caminhos para javax.net.ssl.trustStore .

O mais fácil seria fazer uma cópia local dos cacerts do JRE e importar os certificados de sua outra loja (efetivamente mesclando-os). (Veja keytool -importkeystore .)

Caso contrário, se você souber de antemão que todas as suas conexões LDAP usarão seu segundo keystore (e também desejar poder usar o armazenamento de confiança padrão para outras conexões não relacionadas), poderá configurar esse armazenamento SSLSocketFactory somente para esse SSLSocketFactory . Eu não estou familiarizado com com.org.ldap.LDAPSocketFactory , mas pode ter uma opção para fazer isso. (Caso contrário, você pode criar seu SSLContext personalizado inicializado com seu segundo SSLSocketFactory e obter um SSLSocketFactory , conforme descrito nesta resposta ).

Outra maneira, mais complicada, seria criar um X509TrustManager personalizado que X509TrustManager o gerenciador de confiança padrão, X509TrustManager suas exceções e tente novamente com outro gerenciador de confiança inicializado usando sua segunda loja. É viável, mas você precisa ter certeza de que ainda lança a exceção se nenhum dos gerentes de confiança aceitar o seu certificado (caso contrário, haveria uma falha de segurança). Se você não estiver familiarizado com a API JSSE (ou Java ao todo), provavelmente não é a melhor opção.

Além disso, tenha cuidado ao usar System.setProperty("javax.net.ssl.trustStore", ...) em seu código: é o que é lido para inicializar o SSLContext padrão, mas o SSLContext padrão é inicializado apenas uma vez, primeira vez é necessário. A definição dessa propriedade do sistema posteriormente não teria nenhum efeito (a menos que, é claro, outras classs de outras bibliotecas também dependam desse valor).


Também não está claro o que você está tentando alcançar com isso, pois você sempre terá sucesso em adicionar um provedor de segurança que já está lá:

  try { SSLContext se = SSLContext.getInstance("TLS"); Security.addProvider(se.getProvider()); } catch(NoSuchAlgorithmException e) { } 

Não, basta importar todos os certificados de um truststore para o outro e usar o segundo.