Estou desenvolvendo um aplicativo Java que consulta uma API REST em um servidor remoto por HTTP. Por motivos de segurança, essa comunicação deve ser alterada para HTTPS.
Agora que o Let's Encrypt começou sua versão beta pública, eu gostaria de saber se o Java atualmente funciona (ou se está confirmado que está funcionando no futuro) com seus certificados por padrão.
Vamos Encrypt ter seu intermediário assinado pela IdenTrust , o que deve ser uma boa notícia. No entanto, não consigo encontrar nenhum desses dois na saída deste comando:
keytool -keystore "..\lib\security\cacerts" -storepass changeit -list
Sei que CAs confiáveis podem ser adicionadas manualmente em cada máquina, mas como meu aplicativo deve ser gratuito para download e executável sem nenhuma configuração adicional, estou procurando soluções que funcionem "prontas para uso". Você tem boas notícias para mim?
Respostas:
[ Atualização 2016-06-08 : de acordo com https://bugs.openjdk.java.net/browse/JDK-8154757, a CA do IdenTrust será incluída no Oracle Java 8u101.]
[ Atualização 05/08/2016 : O Java 8u101 foi lançado e inclui de fato a CA IdenTrust: notas de versão ]
Sim. O certificado Let's Encrypt é apenas um certificado de chave pública comum. O Java suporta (de acordo com Let's Encrypt Certificate Compatibility , para Java 7> = 7u111 e Java 8> = 8u101).
Não / depende da JVM. O armazenamento confiável do Oracle JDK / JRE até 8u66 não contém a CA Let's Encrypt criptografada especificamente nem a CA IdenTrust que a assinou cruzadamente.
new URL("https://letsencrypt.org/").openConnection().connect();
por exemplo, resulta emjavax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
.No entanto, você pode fornecer seu próprio validador / definir um keystore personalizado que contenha a CA raiz necessária ou importar o certificado para o armazenamento confiável da JVM.
https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 também discute o tópico.
Aqui está um código de exemplo que mostra como adicionar um certificado ao armazenamento confiável padrão no tempo de execução. Você só precisará adicionar o certificado (exportado do firefox como .der e colocar no caminho de classe)
Baseado em Como posso obter uma lista de certificados raiz confiáveis em Java? e http://developer.android.com/training/articles/security-ssl.html#UnknownCa
fonte
isrgrootx1.der
elets-encrypt-x1-cross-signed.der
, mas nenhum deles parece ser o caminho certo.https://helloworld.letsencrypt.org
por exemplo, e inspecione a cadeia de certificados no navegador (clicando no ícone verde). Para este, você precisa do certificado específico do site, o intermediário X1 (assinado em cruz por IdenTrust) ou o DSTRootCAX3. OISRG Root X1
não funciona no site helloworld porque não está na cadeia, é a cadeia alternativa. Eu usaria o DSTRoot, simplesmente exportado pelo navegador, porque não o vi para download em nenhum lugar.javax.net.ssl.trustStore
propriedade do sistema, mas -1 por definir o padrão da JVMSSLContext
. Seria melhor criar um novoSSLSocketFactory
e depois usá-lo para várias conexões (por exemploHttpUrlConnection
), em vez de substituir a configuração SSL em toda a VM. (Sei que esta alteração só é eficaz para a JVM em execução e não persistir ou afetar outros programas que eu só acho que é uma melhor prática de programação para ser explícito sobre onde sua configuração se aplica..)Sei que o OP solicitou uma solução sem alterações na configuração local, mas caso você queira adicionar a cadeia de confiança ao keystore permanentemente:
fonte: https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/13
fonte
Resposta detalhada para aqueles de nós dispostos a fazer alterações locais na configuração, incluindo o backup do arquivo de configuração:
1. Teste se está funcionando antes das alterações
Se você ainda não possui um programa de teste, pode usar meu programa ping SSLPing java que testa o handshake TLS (funcionará com qualquer porta SSL / TLS, não apenas HTTPS). Usarei o SSLPing.jar predefinido, mas ler o código e construí-lo você mesmo é uma tarefa rápida e fácil:
Como minha versão do Java é anterior a 1.8.0_101 (não liberada no momento da redação deste documento), um certificado Let's Encrypt não será verificado por padrão. Vamos ver como é a falha antes de aplicar a correção:
2. Importe o certificado
Estou no Mac OS X com o conjunto de variáveis de ambiente JAVA_HOME. Os comandos posteriores assumirão que esta variável está definida para a instalação do java que você está modificando:
Faça um backup do arquivo cacerts que modificaremos para que você possa fazer o backup de qualquer alteração sem reinstalar o JDK:
Faça o download do certificado de assinatura que precisamos importar:
Execute a importação:
3. Verifique se está funcionando após as alterações
Verifique se o Java está feliz em se conectar à porta SSL:
fonte
Para o JDK que ainda não suporta certificados Let's Encrypt, você pode adicioná-los ao JDK
cacerts
após este processo (graças a isso ).Faça o download de todos os certificados em https://letsencrypt.org/certificates/ (escolha o formato der ) e adicione-os um a um com este tipo de comando (exemplo para
letsencryptauthorityx1.der
):fonte