Como acessar um WebService via HTTPS estando o certificado/chave privada num Token USB (eCNPJ)?

[quote=lcspohn]Boa tarde elissandromendes

Estou com o mesmo problema seu, verifiquei o seguinte (token da rainbow);

No token existe a seguinte cadeia:
[color=blue] AC Raiz
AC Secretaria da Receita Federal do Brasil
AC Serasa RFB
Empresa com o certificado E-CNPJ
[/color]

No momento que executo o comando:

ks.load(null, new String("xxxxxx").toCharArray());

o mesmo me retorna a informaçao da AC Secretaria da Receita Federal do Brasil (subject=CN=AC Secretaria da Receita Federal do Brasil, O=ICP-Brasil, C=BR)
no entanto deveria vir a informação do “Empresa com o certificado E-CNPJ”.

Como que está retornando para ti esta informação?

Talvez já tenha resolvido, pela data, é bem antiga, teria alguma resposta para mim?

Muito obrigado
[/quote]

Neste caso, você precisa “varrer” os certificados que retornam do token e tentar extrair a PK. Quando conseguir, será o certificado do seu cliente.
Caso contrário, é tão somente um certificado da cadeia validadora.
Para facilitar eu criei um arquivo de configuração onde o meu sistema extrai o alias correto e seta neste arquivo.
Isso evita que tenha que pesquisar todas as vezes que vai usar o token/cartão. Além disso, caso o processo falhe na localização do alias correto,
ainda tenho a possibilidade de setá-lo a mão.

Alencar

Boa Tarde Alencar

Muito obrigado pelo retorno.

Ref. ao que vc falou, eu já faço isso, segue modelo que fiz para teste:

	KeyStore ks = KeyStore.getInstance("PKCS11");
	ks.load(null, certificado.getcertificadoPassword().toCharArray());
	
    Enumeration<String> aliasesEnum = ks.aliases();
    while (aliasesEnum.hasMoreElements()) {  
        String alias = (String) aliasesEnum.nextElement();
	        
        X509Certificate certif = (X509Certificate)ks.getCertificate(alias);
        System.out.println( "SN =     " + certif.getSerialNumber().toString(16) );
        System.out.println( "Issuer = " + certif.getIssuerDN().toString() );
        System.out.println( "subject= " + certif.getSubjectDN().toString() );
	}

Neste caso acima é para varrer todos os certificados que existem no token.

Normalmente só traz o certificado da empresa e neste token que eu tenho está estranho, está trazendo somente o da secretaria da receita federal.

[color=red]SunPKCS11-Safenetikey2032 RSA private key, 1024 bits (id 2621440, token object, sensitive, unextractable)
SN = 5
Issuer = CN=Autoridade Certificadora Raiz Brasileira v1, OU=Instituto Nacional de Tecnologia da Informacao - ITI, O=ICP-Brasil, C=BR
subject= CN=AC Secretaria da Receita Federal do Brasil, O=ICP-Brasil, C=BR
[/color]

No subject deveria trazer o nome da empresa e ou cnpj, se eu visualizar este certificado pelo próprio token está correto e pelo internet explorer também, consegui emitir uma nota fiscal pelo site da receita normalmente com este token.

Mas via código java não consigo, estou utilizando a versão 1.6.0_20 do java.

Eis o motivo pelo qual fiz um arquivo de configuração. Quando nada mais funciona, seto o alias do certificado certo no braço.

Alencar

Bom dia Alencar,

Mas neste caso o arquivo de configuiração para mim não irá resolver, fiz este teste não deu certo, o problema que não aparece os certificados após o load.
Pode ser que eu esteja enganado, mas o código abaixo deveria listar todos os certificados no token, correto?

[code]Provider p = new sun.security.pkcs11.SunPKCS11(getcertificadoFile());

Security.addProvider§;

KeyStore ks = KeyStore.getInstance(“PKCS11”);
ks.load(null, null);

Enumeration aliasesEnum = ks.aliases();
while (aliasesEnum.hasMoreElements()) {
String alias = (String) aliasesEnum.nextElement();

System.out.println("----> Certificado alias: " + alias + "    Key store type: " + ks.getType());
X509Certificate certif = (X509Certificate)ks.getCertificate(alias);
System.out.println( "SN =     " + certif.getSerialNumber().toString(16) );
System.out.println( "Issuer = " + certif.getIssuerDN().toString() );
System.out.println( "subject= " + certif.getSubjectDN().toString() );

}

[/code]

No entanto só me mostra uma cadeia.

o problema é: No IE mostra a cadeia completa e o certificado está OK (Repositório de certificados do windows), já neste código acima só mostra um certificado da cadeia, no caso o da secretaria da receita federal. Será por que?

[quote=lcspohn]Bom dia Alencar,

…o problema é: No IE mostra a cadeia completa e o certificado está OK (Repositório de certificados do windows), já neste código acima só mostra um certificado da cadeia, no caso o da secretaria da receita federal. Será por que?

[/quote]

Ja tive casos em que foi necessário incluir no token a cadeia certificadora correta, pois a que tinha no token não validava o
certificado do cliente.
No IE, a cadeia é auto instalada (não sei como), por isso lá você vê ela completa.

O que eu faço: Pelo software de instalação/administração do token, analiso a cadeia visualmente. Caso ela não feche com o certificado
ou falte parte dela, importo o certificado correto/restante pelo software do token.

QQ coisa, contate-me em pvt. Após resolver o problema, você publica a solução aqui, para conhecimento de todos.

Alencar

Olá Meus Camaradas, eu já to sendo chamado se São Jorge aqui na firma.

Segue abaixo o codigo que usei para assinar e enviar com o SmartCard da Safeweb, por pendrive é a mesma coisa, só que já vou avisando, fica consideravelmente lento para um numero grande de nf-es.

Espero que ajude.

[code] try {

		String tag = "infNFe";
		String caminhoCertificado = Utilitario.caminhoCertCli();
		String senha = Utilitario.senhaCertCli();
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(false);
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document docs = builder.parse(new File(caminhoNfe));
		
		NodeList elements = docs.getElementsByTagName(tag);
		Element el = (Element) elements.item(0);
		String id = el.getAttribute("Id");
		
		NodeList elements2 = docs.getElementsByTagName("nNF");
		Element elIdNfe = (Element) elements2.item(0);
		idNfeS = elIdNfe.getTextContent();
		
		String providerName = System.getProperty(PROVIDER_NAME, PROVIDER_CLASS_NAME);
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());		

		ArrayList transformList = new ArrayList(); 
		TransformParameterSpec tps = null; 
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED,tps); 
		Transform c14NTransform = fac.newTransform(C14N_TRANSFORM_METHOD, tps); 
		transformList.add(envelopedTransform); 
		transformList.add(c14NTransform); 

		Reference ref = fac.newReference("#" + id, fac.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null); 
		SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,(C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); 

		//A3
		Provider p = new sun.security.pkcs11.SunPKCS11("c:/sistema/token.cfg");
		Security.addProvider(p);
		
		X509Certificate certificado = null;
		KeyStore ks = null;
		try {
			ks = KeyStore.getInstance("PKCS11");
		} catch (KeyStoreException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		try {
			ks.load(null, "safeweb".toCharArray());
		} catch (NoSuchAlgorithmException e) {
			log.info("Erro Assinatura Envio 1: " + e.getMessage());
			e.printStackTrace();
		} catch (CertificateException e) {
			log.info("Erro Assinatura Envio 2: " + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			log.info("Erro Assinatura Envio 3: " + e.getMessage());
			e.printStackTrace();
		}
		
		Enumeration aliasesEnum = ks.aliases(); 
		String alias = ""; 
		while (aliasesEnum.hasMoreElements()) { 
			alias = (String) aliasesEnum.nextElement(); 
			if (ks.isKeyEntry(alias)) {
				//log.info("Entrou: " + alias);
				certificado = (X509Certificate) ks.getCertificate(alias);
				break; 
			} 
		} 


		//A3
                    //aqui eu coloquei fixo, mas, pode ficar conforme a linha de baixo
		KeyStore.PrivateKeyEntry keyEntryA3 = (PrivateKeyEntry) ks.getEntry("3ab3ec9f-2b00-434e-9b88-4154f3853a08", new KeyStore.PasswordProtection("safeweb".toCharArray()));
                    //KeyStore.PrivateKeyEntry keyEntryA3 = (PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection("safeweb".toCharArray()));
		X509Certificate cert = (X509Certificate) keyEntryA3.getCertificate();
					
		//log.info("Certificado: " + keyEntryA3);
		KeyInfoFactory kif = fac.getKeyInfoFactory(); 
		List x509Content = new ArrayList(); 
		
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content); 
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd)); 

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
		dbf.setNamespaceAware(true); 
		Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(caminhoNfe)); 

		DOMSignContext dsc = new DOMSignContext(keyEntryA3.getPrivateKey(), doc.getDocumentElement().getElementsByTagName("NFe").item(0));
		
		XMLSignature signature = fac.newXMLSignature(si, ki); 
		signature.sign(dsc); 

		doc.setXmlStandalone(true);
		
		NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); 
		
		if (nl.getLength() == 0) { 
			throw new Exception("Elemento assinatura não encontrado"); 
		} 
		DOMValidateContext valContext = new DOMValidateContext( new X509KeySelector(ks), nl.item(0)); 
		XMLSignature signatures = fac.unmarshalXMLSignature(valContext); 
		boolean coreValidity = signatures.validate(valContext); 
		if (coreValidity == false) { 
			System.err.println("Falha na Assinatura!");			
			log.info("Falha na Assinatura da NF-e " + idNfeS);				
		} else { 
			System.out.println("Assinatura Correta!");				
			log.info("Assinatura  da NF-e " + idNfeS + " correta.");
		} 
					
		OutputFormat format    = new OutputFormat(doc); 
		StringWriter stringOut = new StringWriter ();    
    	XMLSerializer serial   = new XMLSerializer (stringOut,format);
	    serial.serialize(doc);
	    
	    nfeDadosMsg = stringOut.toString();
	
	} catch (Exception e){
		texto.append("Exception a: " + e.getMessage() + "\n");
		texto.setCaretPosition(texto.getText().length());
		texto.repaint();
	}

	String retornoProc = null;
	
	Provider p = new sun.security.pkcs11.SunPKCS11("c:/sistema/token.cfg");
	Security.addProvider(p);
			
	KeyStore ks = null;
	try {
		ks = KeyStore.getInstance("PKCS11");
	} catch (KeyStoreException e2) {
		// TODO Auto-generated catch block
		e2.printStackTrace();
	}
	try {
		ks.load(null, "safeweb".toCharArray());			
	} catch (NoSuchAlgorithmException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (CertificateException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	Enumeration aliasesEnum = null;
	try {
		aliasesEnum = ks.aliases();
	} catch (KeyStoreException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	while (aliasesEnum.hasMoreElements()) {
	   String alias = (String)aliasesEnum.nextElement();
	   X509Certificate cert = null;
	   try {
		   cert = (X509Certificate) ks.getCertificate(alias);			   
		   certificadoVector.add(cert);
	   } catch (KeyStoreException e) {
		   // TODO Auto-generated catch block
		   e.printStackTrace();
	   }
	   
	   //System.out.println("Certificate: " + cert);
	   PrivateKey privateKey = null;
	   try {
		   privateKey = (PrivateKey) ks.getKey(alias, null);
	   } catch (UnrecoverableKeyException e) {
		   // TODO Auto-generated catch block
		   e.printStackTrace();
	   } catch (KeyStoreException e) {
		   // TODO Auto-generated catch block
		   e.printStackTrace();
	   } catch (NoSuchAlgorithmException e) {
		   // TODO Auto-generated catch block
		   e.printStackTrace();
	   }
	   //System.out.println("Private key: " + privateKey);
	}
	
	DocumentBuilderFactory factoryV = DocumentBuilderFactory.newInstance();
    System.out.println("DocumentBuilderFactory: "+ factoryV.getClass().getName());
    
System.setProperty("javax.net.ssl.keyStoreType", ks.getType());   
    System.setProperty("javax.net.ssl.keyStore", "NONE"); 
    System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-Safeweb");   
    System.setProperty("javax.net.ssl.keyStorePassword", "safeweb");   
	
    System.setProperty("javax.net.ssl.trustStoreType", Utilitario.tipoCertSrv());
	System.setProperty("javax.net.ssl.trustStore", Utilitario.caminhoCertSrv());//Aqui vem o arquivo criado através do comando keytool no passo 3
	System.setProperty("javax.net.ssl.trustStorePassword", Utilitario.senhaCertSrv());//Aqui a senha deste keystore
	
	//versao 2.00
	br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsg cabecalho = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsg();
	cabecalho.setCUF("43");
	cabecalho.setVersaoDados("2.00");

	br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsgE cabE = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsgE();     
	cabE.setNfeCabecMsg(cabecalho);     
	
	OMElement el = null;
	try {
		el = AXIOMUtil.stringToOM(nfeDadosMsg);
	} catch (XMLStreamException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
	
	el.build();
	System.out.println("el -> " + el.toString());
	
	br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeDadosMsg dadosMsg = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeDadosMsg();
	//dadosMsg.setExtraElement(oNfeDadosMsg.getFirstElement());
	dadosMsg.setExtraElement(el);

	br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeRecepcaoLote2Result result = null;
	try {
		result = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub().nfeRecepcaoLote2(dadosMsg, cabE);			
	} catch (AxisFault e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (RemoteException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

[/code]

Pessoal, pegando o código do repositório do windows conseguir assinar o aquivo

[code]// KeyStore ks = KeyStore.getInstance(“PKCS11”);
KeyStore ks = KeyStore.getInstance(“Windows-MY”);
ks.load(null, certificado.getcertificadoPassword().toCharArray());

Enumeration aliasesEnum = ks.aliases();
while (aliasesEnum.hasMoreElements()) {
String alias = (String) aliasesEnum.nextElement();

X509Certificate certif = (X509Certificate)ks.getCertificate(alias);
System.out.println( "SN = " + certif.getSerialNumber().toString(16) );
System.out.println( "Issuer = " + certif.getIssuerDN().toString() );
System.out.println( "subject= " + certif.getSubjectDN().toString() );
}
[/code]

Mas, no momento que assinar pede a senha PIN na tela e no momento que tentar enviar para a SEFAZ apresente erro:

[quote]; nested exception is:
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

[/quote]

Pessoal,

Bom dia!

Estou com um problema com o token ikey2032.

Para me conectar a base de dados da empresa naqual trabalho utilizo os progrmas pageantsc e puttysc, no windows xp eu configurava o puttysc com a dll (dkck201.dll) onde tinha a chave do meu Certificado.

Com a nova versão para windows 7 (http://loja.certificadodigital.com.br/Serasa/Instale%20o%20token/D162) Minha chave não reconhece.

Tem como descobrir se há uma nova dll para o windows 7 ?

Agradeço muito a ajuda de vocês.

att.:
Fábio Araújo

Consegui…

No Windows XP a DLL que você informava era dkck201.dll, em C:\WINDOWS\system32\ na opção SSH > pkcs11 do Putty.

Para o Windows 7, você terá que informar a dll: eTPKCS11.dll, no mesmo caminho C:\WINDOWS\system32\