Guia definitivo de certificados em Java! Faixa Preta em Keytool

Introdução

0160090458_Ampliada

Para podermos entender o que virá a seguir, precisamos definir alguns conceitos, os quais copiei literalmente do link ao lado, e não tenho méritos nenhum sobre isso(https://crestaniblog.wordpress.com/2013/03/28/criar-certificado-digital/):

  • Autoridade Certificadora, Certificate Authority(CA) – São as entidades responsáveis pela emissão de certificados digitais;
  • Certificado Digital -Arquivos compostos por um par de chaves (Chave Pública e Privativa) e a assinatura de uma terceira parte confiável, Autoridade Certificadora(AC). O padrão mais utilizado para certificados é o ITU-T X.509;
  • Java Keytool – é uma ferramenta de gerenciamento de certificados e chaves;
  • Java Keystore(JKS) -É um repositório chaves e certificados criados por essas chaves, e cada entrada(certificado + chaves) pode ser identificado por um Alias. O próprio arquivo utilizado como Keystore pode ser protegido com senha. Ao acessar um Keystore sem informar a senha apenas os certificados podem ser acessados. Cada chave privada pode possuir sua própria senha, ou seja, para usar uma Chave Privada que está em um Keystore temos que informar duas senhas, uma da Keystore e outra, da Chave Privada;
  • Arquivo cacerts –  é uma Keystore, com a senha changeit, do tipo JKS, que fica em um diretório jre/lib/security na sua instalação do Java;
  • TrustStore – Área de armazenamento de chaves confiáveis. Geralmente contém certificados confiáveis ou apenas certificados das autoridades certificadoras.
  • ICP Brasil – Autoridade Certificadora Brasileira. É a AC-Raiz, o topo da cadeia de certificação e pode credenciar outras entidades certificadoras abaixo dela (ACs intermediárias);
  • PEM – O formato PEM é o mais utilizado pelos CAs e geralmente têm formatos como . Pem. Crt. Cer, e. Key. São arquivos ASCII, codificados em Base64m e seu conteúdo começa por “—–BEGIN CERTIFICATE—– “, e termina por “—–END CERTIFICATE—– “;
  • DER – O formato DER  normalmente utilizado em plataformas Java, é simplesmente uma forma binária de um certificado em formato PEM, em vez de ASCII.  Às vezes você tem extensão .Der, mas muitas vezes têm uma extensão .Cer, então a única maneira de saber a diferença entre eles é abri-lo em um editor de texto e procurar os “—–BEGIN CERTIFICATE—– ” e “—–END CERTIFICATE—– “.
  • PKCS#12 / PFX – Os PKCS # 12 ou PFX é um formato binário para armazenar o certificado de servidor, todos os certificados, raiz, intermediários e a chave privada em um arquivo criptografado.
  • Certificate Signing request(CSR) – nada mais é, do que um bloco de texto encriptado com sua chave privada que contém as informações que serão incluídas no seu certificado(Nome, Empresa, Cidade , ….) e a sua chave pública.

“Atenção crianças, essa matéria cai na prova, estudem! Copiem da lousa que já vou apagar!”

Isto posto. Vamos começar do começo(ai, ai, ai).

Quero comprar um certificado

certificado.0x200Eu pensei em comprar um certificado, apenas para realizar alguns testes com Https, aprender sobre o processo de compra, instalação e utilização de um certificado real, mas é muito caro, os preços começam a partir de R$ 1.500,00, válidos por apenas 1 ano. Segue link com os preços:

Certisign              Serasa

Bem, o tio aqui não tem dinheiro pra ficar jogando pela janela. Logo, vou fazer tudo utilizando um certificado auto-assinado, criado com o keytool. Para fazer os testes com certificados reais, utilizarei os de sites na Internet.

Caso você queira um certificado válido, e não apenas auto-assinado, você precisará gerar uma requisição de assinatura – Certificate Signing Request (CSR), daqui a pouquinho eu ensino, fique tranquilo, abre uma cerveja e vem comigo.

Criando um par de chaves(pública e privada) com o Keytool

Termo-de-retirada-de-chaves-para-visitação-de-imóvel-300x196“Quem quer criar um par de chaves põe o dedo aqui, que a mão já vai fechar!”

Para criar um par de chaves RSA de 2048 bits, com o apelido chavesProgramandoCerto, no arquivo de keystore chamado keystoreProgramandoCerto.jks, devemos executar os passos abaixo:

Entrar no diretório bin, do seu java:

cd /opt/desenvolvimento/jdk1.8.0_45/bin

Executar o keytool, sem esquecer de mandar o arquivo jks gerado para um diretório ao qual você tenha permissão de escrita, no caso enviarei para /home/marcelo/:

keytool -genkeypair -alias chavesProgramandoCerto -keyalg RSA -validity 365 -keystore /home/marcelo/keystoreProgramandoCerto.jks

Traduzindo para o “portugol”, para os júniors de plantão…

FerramentaDeChave -GereUmParDeChavesPraMim -ComOApelidoDe  chavesProgramandoCerto -UsandoOAlgoritmo RSA -ComAValidadeDe 365 dias -ColoqueAsChavesGeradasNoArmazenadorDeChaves /home/marcelo/keystoreProgramandoCerto.jks

Uma sequencia de informações será solicitada para o processo de geração das chaves e da keystore:

  1. Senha da Keystore(keystoreProgramandoCerto.jks):  senhaKeystore; 0160090458_Ampliada
  2. Confirmar a senha da Keystore(keystoreProgramandoCerto.jks):  senhaKeystore; 
  3. Nome e SobrenomeMarcelo Programador;
  4. Unidade Organizacional(departamento): Desenvolvimento;
  5. EmpresaProgramando Certo;
  6. Cidade: São Paulo;
  7. Estado: São Paulo;
  8. Sigla do País: br;
  9. Confirmar os dados: sim ou yes;
  10. Senha do par de chaves(chavesProgramandoCerto)senhaChaves;
  11. Confirmar senha do par de chaves(chavesProgramandoCerto)senhaChaves;

Se você quiser dar uma olhada na sua keystore, pode fazer assim:

keytool -list -v -keystore /home/marcelo/keystoreProgramandoCerto.jks

“Olha a keystore bonitinha do papai, bilu, bilu, bilu!”.

Nossa keystoreProgramandoCerto.jks possui agora a nossa chave pública, a chave privada e os dados e assinatura da Autoridade Certificadora, no caso, uma padrão do keytool que não tem validade real(Auto-Assinado por enquanto).

Fazendo do jeito certo(ambiente de produção) – Gerando uma Requisição de Assinatura(Certificate Signing Request)

LápisVamos então gerar uma requisição de assinatura – Certificate Signing Request (CSR), para assim conseguirmos um Certificado Real, assinado por uma Autoridade Certificadora. Para isso utilizaremos o nosso par de chaves chavesProgramandoCerto, criado anteriormente. Utilizaremos o comando abaixo para gerar a requisição(CSR):

keytool -certreq -alias chavesProgramandoCerto -file /home/marcelo/certificadoProgramandoCerto.csr -keystore /home/marcelo/keystoreProgramandoCerto.jks

Deixa o tio ajudar de novo:

FerramentaDeChave -GereUmaRequisiçãoDeCertificado –UtilizandoAChavePúblicaDoApelido chavesProgramandoCerto -ColocandoElaEOsDadosDoCertificadoNoArquivo /home/marcelo/certificadoProgramandoCerto.csr -UtilizandoAsInformaçõesNecesáriasDoAramazenadorDeChaves /home/marcelo/keystoreProgramandoCerto.jks

Digite a senha, no nosso caso: senhaKeystore

Melzinho na chupeta!

Nesse momento o arquivo certificadoProgramandoCerto.csr deve conter nossos dados pessoais digitados no processo de geração do par de chaves, as nossas chaves pública e privadas.

Agora envie o arquivo certificadoProgramandoCerto.csr, para a sua Autoridade Certificadora predileta, de acordo com as regras da mesma.

Depois de algum tempo a Autoridade Certificadora, irá lhe enviar o seu certificado assinado(depois de pedir documentos e etc), ou seja um arquivo contendo os Dados Cadastrais, as Chaves(Pública e Privada) e assinado pela Autoridade Certificadora.

Vamos considerar que recebemos o arquivo certifcadoProgramandoCertoReal.p7b. Só precisaremos importá-lo com o keytool, rapidinho. Pelo  amor “di Deus”, guarde este arquivo em local seguro, em um HD e na nuvem para não correr o risco de perder e ter que fazer todo o processo novamente e principalmente $ pagar $, novamente.

keytool -import -alias chavesProgramandoCerto -trustcacerts -file certifcadoProgramandoCertoReal.p7b -keystore /home/marcelo/keystoreProgramandoCerto.jks

“Putz, já tô cansando de traduzir, mas vou dar mais um boi”.

FerramentaDeChave -ImporteOCertificado -NoApelido  chavesProgramandoCerto -SePrecisarUseACacertsDoJavaParaValidarACadeiaDeConfiança -DoArquivo certifcadoProgramandoCertoReal.p7b -QueroQueImporteNoMeuArmazenadorDeChaves /home/marcelo/keystoreProgramandoCerto.jks

Provavelmente, além do seu certificado, você receberá o certificado da Autoridade Certificadora Raiz e uma Intermediária. Neste caso execute o comando acima primeiro no Certificado Raiz, depois novamente para o Intermediário e finalmente para o seu certificado.

Você pode também importá-lo para a cacerts que é a keystore padrão do Java. Acho até melhor o real colocar na cacaerts, pois não sei bem o que vai acontecer quando você tentar importar o certificado real em cima do auto-assinado.

Fazendo do jeito que todo programador faz(e algumas empresas em produção)

Essa jeito é para se usado no ambiente de desenvolvimento, testes, etc. Para colocar em um servidor de produção, use SEMPRE o método 1.

O ministério da saúde adverte, isso pode fazer mal ao seu servidor de produção. Produto destinado a ambiente de teste e desenvolvimento.

A nossa keystore keystoreProgramandoCerto, já tem dentro dela tudo o que precisamos no apelido(alias) chavesProgramandoCerto. Já podemos adicionar nossa keystore em um servidor web e utilizar HTTPS(SSL), com o nosso certificado “auto-assinado”.

PERIGO!PERIGO! Ainda não consegui identificar um problema que está ocorrendo comigo, quando gero a chave pelo Ubuntu 64 bits e subo o JETTY estou recebendo um erro de “no cipher suite …”, mesmo quando tento acessar a página Web pelo browser, ocorre erro. No Windows 7 32 bits que utilizo na empresa isso não está acontecendo. PERIGO! PERIGO!

Inicio: Atualização 30 de Junho de 2015 às 18:00

Finalmente após vários dias indo dormir às 2 da manhã, consegui resolver o problema. Como sempre o problema é mais simples do que parece. O que estava acontecendo, é que eu estava adicionando no jetty.xml uma propriedade “certAlias” no sslcontextFactory, o que acabava gerando o erro do “no cipher suite …”. Não lembro como isso veio parar no jetty.xml, deve ser meu remédio para memória que esqueci de tomar.

Linha removida, Jetty funcionando perfeitamente! No Windows, no Ubuntu, em 32 bits, 64 bits, no Java 6, 7 e 8.

Fim: Atualização 30 de Junho de 2015 às 18:00

Mas, para não deixar nossa chave privada passeando por aí, principalmente porque do ambiente de teste ela vai acabar indo parar na produção, vamos ao menos deixar que apenas o certificado seja enviado para a equipe que precisará fazem algum software que acessa nosso Servidor Web, ou seja enviaremos apenas a chave pública.

Podemos exportar o nosso certificado(apenas com a chave pública, óbvio) através do comando abaixo:
keytool -exportcert -alias
chavesProgramandoCerto -file certificadoProgramandoCertoAutoAssinado.cer -keystore /home/marcelo/keystoreProgramandoCerto.jks

E como diria a bruxa do Pica-Pau: “E lá vamos nós!”.
FerramentaDeChava -CriarUmCertificadoPraMim -UtilizandoAsChavesDoApelido chavesProgramandoCerto -GereOArquivoDoCertificadoComONome certificadoProgramandoCerto.der PegueAsInformaçõesNecesáriasDoArmazenadorDeChaves /home/marcelo/keystoreProgramandoCerto.jks

Estou começando a achar que a tradução do portugol, já está mais atrapalhando que ajudando, mas “bora lá”.

Quem precisar utilizar nosso certificado para se conectar em nosso servidor, deverá explicar para o seu Java, que nosso certificado é “confiável”, e poderá fazê-lo através do comando abaixo:

keytool -import -alias chavesProgramandoCerto -trustcacerts -file certificadoProgramandoCertoAutoAssinado.der -keystore /$JAVA_HOME/jre/lib/security/cacerts

ou

keytool -import -alias chavesProgramandoCerto -trustcacerts -file certificadoProgramandoCertoAutoAssinado.der -keystore /QualqueKeyStore.jks

Se quiser uma lista detalhada de todos os parâmetros e funcionalidades do keytool, recomendo que vá à fonte http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html

Chega de blá, blá, blá e vamos programar(ebaaaaa)

Primeiramente pegue o código abaixo e coloque no seu eclipse. Crie um projeto em branco de testes, se é que você já não o tem. Bem, já deveria ter, se vem fazendo os exemplos do Blog.

public class TestarHttpsExemplo {

	public static void main(String[] args) {
		new TestarHttpsExemplo().testIt("https://www.google.com");
	}

	private void testIt(String https_url) {
		try {
			URL url = new URL(https_url);
			HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

			if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {
				String line;
				String response = "";
				BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
				while ((line = br.readLine()) != null) {
					response += line;
				}
				System.out.println(response);
			}
			con.getCipherSuite();
			Certificate[] certs = con.getServerCertificates();

			print_https_cert(con);
			print_content(con);		

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void print_https_cert(HttpsURLConnection con) {
		if (con != null) {
			try {
				System.out.println("Codigo de resposta da URL : " + con.getResponseCode());
				System.out.println("Suide de Criptografia : " + con.getCipherSuite());
				System.out.println("\n");

				Certificate[] certs = con.getServerCertificates();
				for (Certificate cert : certs) {
					System.out.println("Tipo do Certificado........: " + cert.getType());
					System.out.println("Codigo Hash do Certificado.: " + cert.hashCode());
					System.out.println("Algoritmo da Chave Publica.: " + cert.getPublicKey().getAlgorithm());
					System.out.println("Formato do Chave Publica...: " + cert.getPublicKey().getFormat());
					System.out.println("\n");
				}
			} catch (SSLPeerUnverifiedException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void print_content(HttpsURLConnection con) {
		if (con != null) {
			try {
				System.out.println("****** Conteudo da URL ********");
				BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
				String input;
				while ((input = br.readLine()) != null) {
					System.out.println(input);
				}
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

Agora execute a classe passando como parâmetro para o método testIt o valor https://www.google.com, e veja o resultado que deve se parecer com isso(resumido pois desce muita coisa):

Codigo de resposta da URL..: 200
Suite de Criptografia..... : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Tipo do Certificado........: X.509
Codigo Hash do Certificado.: -1600710518
Algoritmo da Chave Publica.: EC
Formato do Chave Publica...: X.509

Tipo do Certificado........: X.509
Codigo Hash do Certificado.: 274418414
Algoritmo da Chave Publica.: RSA
Formato do Chave Publica...: X.509

Tipo do Certificado........: X.509
Codigo Hash do Certificado.: 349192256
Algoritmo da Chave Publica.: RSA
Formato do Chave Publica...: X.509

****** Conteudo da URL ********

Agora execute a classe novamente, mas agora passando como parâmetro para o método testIt o valor https://www.caelum.com.br, e veja o resultado que deve se parecer com isso(resumido novamente):

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1512)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
	at br.com.programandocerto.TestarHttpsExemplo.testIt(TestarHttpsExemplo.java:24)
	at br.com.programandocerto.TestarHttpsExemplo.main(TestarHttpsExemplo.java:16)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:230)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
	... 15 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)

“Mas que porrr.. é essa? Porque não funcionou? o Mestre Marcelo fez algo de errado na classe de exemplo?!?!”

Claro que não! Lembra quando eu disse que o certificado é caro, e às vezes o certificado auto-assinado vai para a produção ao invés de um certificado ass144-google-chrome-self-signed-ssl-certificateinado por uma Autoridade Certificadora? Bem é isso que acontece. O Google que tem “infinito dinheiro”, comprou um certificado real, e a Caelum não.

“Ahhh, você está acusando a Caelum, que em casa de ferreiro o espeto é de pau!?!?!”

Atire a primeira pedra quem nunca pecou! Eles vendem cursos e normalmente tudo é feito por telefone o site é quase que apenas institucional. Quem sabe eles me oferecem um curso pela defesa, ou me proíbem de fazer novos cursos por tê-los utilizados como exemplo.

“Nossa Marcelo, como tú é mentiroso. Porque então que eu consegui abrir o site da Caelum no meu browser, hein, hein?”

Elementar, meu caro Watson! O Browser faz um monte de coisa por debaixo dos panos para que tudo funcione direitinho. Para que nosso código funcione, para o site da Caelum, basta utilizarmos o que foi aprendido aqui neste post. É só importar o certificado da Caelum para a nossa keystore.

“Mas como eu pego o certificado deles? Contrato um Hacker para roubar?”

Deus me livre, “num” fala uma coisa dessas, senão os “homi” fecha meu blog.

Você pode ligar lá e pedir, e as atendentes não vão fazer a menor ideia do que você está falando. Você pode simplesmente clicar no cadeado do browser e pedir para exportar o certificado. Agora sim é só usar o keytool, para importá-lo.

Testando em um Servidor WEB(Jetty)

Já que comecei este tutorial, vou fazer direito. Não só ensinei como pescar, como vou levá-los a pescaria.

Vamos seguir uma receitinha básica, onde precisaremos de:

  1. Um servidor web(jetty);
  2. Uma keystore, com o nosso par de chaves;
  3. Configurar o Jetty para utilizar HTTPS utilizando o nosso par de chaves;

Baixe e descompacte o jetty no seu diretório preferido.

Adicione as configurações abaixo ao arquivo /etc/jetty.xml. Configuraremos o Jetty para utilizar a porta HTTPS na 8443. E também todas as configurações de localização da Keystore e as devidas senhas.

    <Call name="addConnector">
	<Arg>
  	    <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
		<Set name="host"><Property name="jetty.host" /></Set>
		<Set name="port"><Property name="jetty.port" default="8080"/></Set>
		<Set name="maxIdleTime">300000</Set>
		<Set name="Acceptors">2</Set>
		<Set name="statsOn">false</Set>
		<Set name="confidentialPort">8443</Set>
		<Set name="lowResourcesConnections">20000</Set>
		<Set name="lowResourcesMaxIdleTime">5000</Set>
	    </New>
	</Arg>
     </Call>

     <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
  	<Set name="KeyStorePath">/opt/desenvolvimento/jetty8/keystore/keystoreProgramandoCerto.jks</Set>
  	<Set name="KeyStorePassword">senhaKeystore</Set>
	<Set name="keyManagerPassword">senhaChaves</Set>
  	<Set name="TrustStore">/opt/desenvolvimento/jetty8/keystore/keystoreProgramandoCerto.jks</Set>
  	<Set name="TrustStorePassword">senhaKeystore</Set>
     </New>

  <Call name="addConnector">
    <Arg>
      <New class="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
        <Arg><Ref id="sslContextFactory" /></Arg>
        <Set name="Port">8443</Set>
        <Set name="maxIdleTime">30000</Set>
        <Set name="Acceptors">2</Set>
        <Set name="AcceptQueueSize">100</Set>
      </New>
    </Arg>
  </Call>

Coloquei as senhas abertas no arquivo, mas novamente, você deve fazer isso em produção. Utilize a ferramenta de “embaralha o texto” que vem no diretório lib do jetty.

java -cp jetty-util-8.1.17.v20150415.jar org.eclipse.jetty.util.security.Password senhaKeystore

Será gerado algo parecido com isso:

senhaKeystore
OBF:1vv11vn61wu61wmr1v1p1rv51t331rxp1v2p1wnf1wu81vnw1vu9
MD5:8b28fb1926e25938627616636d482a77&lt;/pre&gt;
&lt;pre&gt;

E assim você poderá utilizar o texto OBF:1vv11vn61wu61wmr1v1p1rv51t331rxp1v2p1wnf1wu81vnw1vu9 no lugar da senha senhaKeystore. Repetir o processo para a senha do keyManagerPassword, no nosso caso a senha senhaChaves.

Agora abra o navegador e acesse https://localhost:8443. Se tudo der certo, você verá uma página padrão do Browser com o cadeado e com um X, dizendo que o “site não é confiável”. Selecione a opção de acessar o site mesmo assim, que em cada navegador será de um jeito diferente. Agora você deverá ver uma página padrão do Jetty.error

Vamos executar agora o nosso aplicativo de exemplo(método testIt), mas apontando para https://localhost:8443. Um erro parecido com este surgirá na sua tela.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1747)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1209)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:135)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:943)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
	at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
	at br.com.marcelo.TestarHttps.testIt(TestarHttps.java:47)
	at br.com.marcelo.TestarHttps.main(TestarHttps.java:21)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
	at sun.security.validator.Validator.validate(Validator.java:218)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1188)
	... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)

Execute novamente, mas agora passando como parâmetro da VM o texto abaixo:

-Djavax.net.ssl.trustStore=/home/marcelo/keystoreProgramandoCerto.jks

Isso fará com que a JVM busque nessa keystore as chaves necessárias para o handshake da conexão SSL(HTTPS). Dever ser a keystore onde importamos o certificado, que pode ter sido a  cacerts ou uma keystore qualquer onde o certificado foi importado. Agora sim, finalmente o código funcionará. “Tenha fé, porque até no lixão nasce flôr”, já diria Mano Brown.

Flor e lixo web

Bibliografia

http://intoweb.blogspot.com.br/2008/09/importando-certificados-ssl-para-jvm.html

https://crestaniblog.wordpress.com/2013/03/28/criar-certificado-digital/

https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores

http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html

http://support.attachmate.com/techdocs/2680.html

https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores

Um comentário em “Guia definitivo de certificados em Java! Faixa Preta em Keytool

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s