NFe - o que realmente vai na propriedade javax.net.ssl.trustStore?

Ficou um pouco confuso qual valor que vai realmente nesse propriedade.

Em vários posts eu vi que o que vai nela é o caminho para o arquivo .keystore criado com o keytool a partir do arquivo .cer

Já em outros posts eu vi que o que vai nela é o caminho para o arquivo jssecacerts que deve ser criado com um código que foi colocado nesse post

No meu estava apontando para o arquivo .keystore que eu tinha criado com o keytool, porém estou recebendo essa exception, a qual fui investigar e alguns artigos/posts indicam que tem que criar esse arquivo jssecacerts:

[code] Provider p = new sun.security.pkcs11.SunPKCS11(NFe.CAMINHO_ARQUIVO_CONFIG);
Security.addProvider§;
KeyStore ks = KeyStore.getInstance(NFe.TIPO_KEYSTORE_A3); // PKCS11
ks.load(null, NFe.SENHA_CERTIFICADO.toCharArray());
System.setProperty(“java.protocol.handler.pkgs”, “com.sun.net.ssl.internal.www.protocol”);
System.setProperty(“javax.net.ssl.keyStore”, “NONE”);
System.setProperty(“javax.net.ssl.keyStoreType”, ks.getType());
System.setProperty(“javax.net.ssl.keyStorePassword”, NFe.SENHA_CERTIFICADO);

    System.setProperty("javax.net.ssl.trustStoreType", "JKS");
    System.setProperty("javax.net.ssl.trustStore", NFe.CAMINHO_ARQUIVO_KEYSTORE); //Aqui.....
    System.setProperty("javax.net.ssl.trustStorePassword", NFe.SENHA_KEYSTORE);

[/code]

org.apache.axis2.AxisFault: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:83) at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84) at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499) at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114) at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096) at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:346) at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:542) at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:199) at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:76) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:400) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:225) at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:435) at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:402) at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229) at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165) at emissor.webservices.status2.NfeStatusServico2Stub.nfeStatusServicoNF2(NfeStatusServico2Stub.java:174) at emissor.lib.NFe.statusServico(NFe.java:125) at emissor.ui.NotasFiscaisUI.iniciarUI(NotasFiscaisUI.java:91) at emissor.ui.NotasFiscaisUI.formComponentShown(NotasFiscaisUI.java:533) at emissor.ui.NotasFiscaisUI.access$400(NotasFiscaisUI.java:69) at emissor.ui.NotasFiscaisUI$6.componentShown(NotasFiscaisUI.java:374) at java.awt.Component.processComponentEvent(Component.java:6095) at java.awt.Component.processEvent(Component.java:6043) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Caused by: com.ctc.wstx.exc.WstxIOException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:313) at org.apache.axiom.om.impl.MTOMXMLStreamWriter.flush(MTOMXMLStreamWriter.java:168) at org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer.flush(MTOMAwareXMLSerializer.java:79) at org.apache.axiom.om.impl.MTOMXMLStreamWriter.flush(MTOMXMLStreamWriter.java:168) at org.apache.axiom.om.impl.llom.OMNodeImpl.serialize(OMNodeImpl.java:388) at emissor.webservices.status2.NfeStatusServico2Stub$NfeDadosMsg.serialize(NfeStatusServico2Stub.java:1970) at emissor.webservices.status2.NfeStatusServico2Stub$NfeDadosMsg.serialize(NfeStatusServico2Stub.java:1915) at emissor.webservices.status2.NfeStatusServico2Stub$NfeDadosMsg$1.serialize(NfeStatusServico2Stub.java:1903) at org.apache.axis2.databinding.ADBDataSource.serialize(ADBDataSource.java:93) at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerializeAndConsume(OMSourcedElementImpl.java:738) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:966) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:995) at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:254) at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:242) at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:995) at org.apache.axiom.om.impl.llom.OMNodeImpl.serializeAndConsume(OMNodeImpl.java:486) at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:79) ... 36 more Caused by: 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:1623) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:192) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1074) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:128) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623) at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59) at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65) at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123) at org.apache.commons.httpclient.ChunkedOutputStream.flush(ChunkedOutputStream.java:191) at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:99) at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:214) at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:311) ... 52 more 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:294) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:200) 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:1053) ... 65 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:289) ... 71 more
Uma ajuda seria bem vinda.

Obrigado

Eu coloco o caminho do keystore.

Geralmente esse erro é porque está faltando algum certificado no seu keystore, ou ele expirou. Você deve incluir todos os certificados, inclusive o raiz.

Sinceramente não entendo muito bem disso, se puder me dar uma luz.

Eu tenho um certificado A3 (eToken da Certisign) - na verdade são dois porque são duas empresas que vão emitir notas da mesma máquina- instalei o certificado pelo navegador e exportei para um arquivo .cer, depois fui na linha de comando e criei um .keystore com o keytool.

O que significa “incluir todos os certificados, inclusive o raiz”?

O certificado é “novinho” e vai demorar bastante para expirar.

O que fiz errado?

System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");  
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());  
System.setProperty("javax.net.ssl.keyStore", "caminho do arquivo pfx");
System.setProperty("javax.net.ssl.keyStorePassword", "senha");//Aqui a senha deste certificado

System.setProperty("javax.net.ssl.trustStoreType", "JKS");  
System.setProperty("javax.net.ssl.trustStore", "caminho do .keystore");

O Certificado do cliente não fica junto do keystore, os certificados que vão no keystore são encontrados no site da SEFAZ, geralmente são arquivos .p7b, vc instala eles e exporta e logo em seguida importa no keytool do java

Então no keystore não é o certificado do cliente?

Onde eu pego esse certificado no SEFAZ?

Tenho que fazer isso no cliente também ou só tenho que criar os arquivos .keystore uma vez e usar no sistema?

Geralmente você faz apenas uma vez, até eles trocarem o certificado, ai vc faz de novo

Eles ficam na sessão de downloads(geralmente).

No Keystore eu coloco os certificados para poder acessar o WS, o do cliente só é usado para assinar o xml

Nossa! obrigado pelas dicas.

Olha, baixei os 2 certificados daqui e instalei apenas o de homologação, como eu exporto ele agora para um arquivo para que eu possa usar o keytool e gerar o arquivo keystore?

Os certificados geralmente ficam no site da SEFAZ. Ex: http://www.fazenda.sp.gov.br/nfe/downloads/arquivos_vigentes.asp

Aqui explica +/- como importa os certificados http://www.guj.com.br/posts/list/15/126061.java

No zip que peguei no SEFAZ tem a descrição dos certificados e a validade, o de homologação tem validade para 17 de junho de 2010:

[quote]Chaves Públicas dos Certificados Digitais em uso nos WS versão 2.00 da SEFAZ/SP.

Ambiente de homologação: SEFAZSP_homologacao.p7b - validade: 17/06/2010, emitida por AC CertiSign Multipla G3
Ambiente de produção : SEFAZSP_producao.p7b - validade: 31/03/2011, emitida por AC Imprensa Oficial SP RFB G2[/quote]

Tá certo isso mesmo?

Está errado

Tem que procurar a versão nova, ou tentar usar esses, ou talvés o de produção funcione

Pois é, mas lá só tem esse arquivo para baixar.

Já instalei o de produção, fui no IE e exportei como Base-64 encoded X.509 (.cer) e depois gerei o KS com o keytool.
keytool -import -alias nfe_producao -keystore nfe_producao.ks -file nfe.fazenda.sp.gov.br-producao.cer

Agora passei o caminho do arquivo .ks e a senha que informei na criação nas propriedades, tentei verificar o status do serviço e nada.

[code] Provider p = new sun.security.pkcs11.SunPKCS11(NFe.CAMINHO_ARQUIVO_CONFIG);
Security.addProvider§;

    KeyStore ks = KeyStore.getInstance(NFe.TIPO_KEYSTORE_A3); // PKCS11
    ks.load(null, NFe.SENHA_CERTIFICADO.toCharArray());
    
    System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
    System.setProperty("javax.net.ssl.keyStore", "NONE");
    System.setProperty("javax.net.ssl.keyStoreType", ks.getType());
    System.setProperty("javax.net.ssl.keyStorePassword", NFe.SENHA_CERTIFICADO);

    System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-eToken-Lamiprint");

    System.setProperty("javax.net.ssl.trustStoreType", "JKS");

    System.setProperty("javax.net.ssl.trustStore", NFe.ARQUIVO_KS_SEFAZ_PRODUCAO);
    System.setProperty("javax.net.ssl.trustStorePassword", NFe.SENHA_KS_SEFAZ_PRODUCAO);

[/code]

Código para verificar o status (pelo menos um contato com o servidor):

[code] NFe.setPropriedadesCertificado();
String cUF = “35”; // SP
String tipoAmbiente = “2”; //1=homologacao, 2=producao
String versao = “2.00”;
String nfeDadosMsg = “”
+ “”
+ " <consStatServ versao="" + versao + “” xmlns=“http://www.portalfiscal.inf.br/nfe">"
+ " " + tipoAmbiente + “”
+ " " + cUF + “”
+ " STATUS”
+ " "
+ “”;

    NfeStatusServico2Stub nfe = new NfeStatusServico2Stub("https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/NfeStatusServico2.asmx");

    NfeCabecMsgE nfeCabecMsg1 = new NfeCabecMsgE();
    NfeCabecMsg param = new NfeCabecMsg();

    param.setCUF(cUF);
    param.setVersaoDados(versao);
    nfeCabecMsg1.setNfeCabecMsg(param);

    OMElement ome = AXIOMUtil.stringToOM(nfeDadosMsg);

    NfeDadosMsg nf2 = new NfeDadosMsg();
    nf2.setExtraElement(ome);

    NfeStatusServicoNF2Result resp = nfe.nfeStatusServicoNF2(nf2, nfeCabecMsg1);
    System.out.println("Retorno : \n" + resp.getExtraElement().toString());[/code]

Na última linha onde eu mando imprimir dá uma cadeia de 3 exceptions, e a primeira de baixo pra cima:

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:289)
Alguma sugestão?

Opa!!! Agora a coisa mudou um pouco.

O que fiz: acessei a URL de homologação para ver o status do serviço e instalei o certificado de homologação diretamente de lá, esse vence em 7 de junho de 2011, refiz todo o processo com o keytool e tentei verificar o status.

Agora me deu essa exception:

org.apache.axis2.AxisFault: HelloRequest followed by an unexpected handshake message at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:203) at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:76) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:400) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:225) at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:435) at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:402) at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229) at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165) at emissor.webservices.status2.NfeStatusServico2Stub.nfeStatusServicoNF2(NfeStatusServico2Stub.java:174) at emissor.lib.NFe.statusServico(NFe.java:152) at emissor.ui.NotasFiscaisUI.iniciarUI(NotasFiscaisUI.java:91) at emissor.ui.NotasFiscaisUI.formComponentShown(NotasFiscaisUI.java:533) at emissor.ui.NotasFiscaisUI.access$400(NotasFiscaisUI.java:69) at emissor.ui.NotasFiscaisUI$6.componentShown(NotasFiscaisUI.java:374) at java.awt.Component.processComponentEvent(Component.java:6095) at java.awt.Component.processEvent(Component.java:6043) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Caused by: javax.net.ssl.SSLException: HelloRequest followed by an unexpected handshake message at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:188) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloRequest(ClientHandshaker.java:286) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:114) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:525) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:746) at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read(BufferedInputStream.java:237) at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78) at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106) at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116) at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.readLine(MultiThreadedHttpConnectionManager.java:1413) at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973) at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735) at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1098) at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:346) at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:542) at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:199) ... 26 more
O que significa isso?

Respondendo para mim mesmo e encerrando esse post.
Para resolver o problema da exception citada na mensagem anterior adicionei a seguinte linha:

// para resolver: HelloRequest followed by an unexpected handshake message System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");