GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Assinaturas de arquivos xml da NFe


#1

Boa tarde a todos
Aqui na empresa estamos tendo problemas para assinar o xml para o envio dos dados da NFe. O web service da receita sempre retorna o erro:
297 Rejeição: Assinatura difere do calculado
Acho que o erro está no campo SignatureValue da assinatura. Alguém conseguiu fazer a assinatura funcionar?

Abaixo está o código que usei: (encontrei o código aqui no forum e adaptei)

[code]public static String sign(String xml) {
	OutputStream os = null;
	String CANONICALIZE_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
	String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
	String PROVIDER_CLASS_NAME = "org.jcp.xml.dsig.internal.dom.XMLDSigRI";
	String PROVIDER_NAME = "jsr105Provider";
	ByteArrayInputStream inXML = new ByteArrayInputStream(xml.getBytes());
	try {
		DocumentBuilderFactory factory = DocumentBuilderFactory
				.newInstance();
		factory.setNamespaceAware(false);
		// Obtem DOM do documento
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(inXML);

		// Obtem elemento do documento a ser assinado, será criado uma
		// REFERENCE para o mesmo
		NodeList elements = doc.getElementsByTagName("infNFe");
		org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(0);
		String id = el.getAttribute("Id");

		// Cria uma factory representando o elemento XML Signature, a partir
		// dela serão criados as parte desse elemento
		String providerName = System.getProperty(PROVIDER_NAME,
				PROVIDER_CLASS_NAME);
		XMLSignatureFactory signatureFactory = XMLSignatureFactory
				.getInstance("DOM", (Provider) Class.forName(providerName)
						.newInstance());

		// Cria método de Digest e canonicalização
		DigestMethod digestMethod = signatureFactory.newDigestMethod(
				DigestMethod.SHA1, null);
		C14NMethodParameterSpec c14NMethodParameterSpec = null;
		CanonicalizationMethod canonicalMethod = signatureFactory
				.newCanonicalizationMethod(CANONICALIZE_METHOD,
						c14NMethodParameterSpec);

		// Cria classe representando o Hash e algoritmo de criptografia a
		// ser aplicado
		SignatureMethod sm = signatureFactory.newSignatureMethod(
				SignatureMethod.RSA_SHA1, null);

		// Cria a lista de tranformações a serem aplicadas as referencias a
		// serem assinadas
		ArrayList transformList = new ArrayList();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = signatureFactory.newTransform(
				Transform.ENVELOPED, tps);
		Transform c14NTransform = signatureFactory.newTransform(
				C14N_TRANSFORM_METHOD, tps);
		transformList.add(envelopedTransform);
		transformList.add(c14NTransform);

		// Cria referencia, parte do XML a ser assinado
		Reference ref = signatureFactory.newReference("#" + id,
				digestMethod, transformList, null, null);
		ArrayList refList = new ArrayList();
		refList.add(ref);

		SignedInfo signedInfo = signatureFactory.newSignedInfo(
				canonicalMethod, sm, refList);


		String configName = "/token.cfg";
		Provider p = new sun.security.pkcs11.SunPKCS11(configName);
		Security.addProvider(p);

		char[] pin = { 's', 'a', 'f', 'e', 'w', 'e', 'b' };
		KeyStore ks = KeyStore.getInstance("pkcs11");
		ks.load(null, pin);
		KeyStore.PrivateKeyEntry pkEntry = null;
		Enumeration aliasesEnum = ks.aliases();
		PrivateKey privateKey = null;
		String alias = "";
		while (aliasesEnum.hasMoreElements()) {
			alias = (String) aliasesEnum.nextElement();
			System.out.println(alias);
			if (ks.isKeyEntry(alias)) {
				privateKey = (PrivateKey) ks.getKey(alias, new String(
						"safeweb").toCharArray());
				break;
			}
		}
		Certificate certificate = ks.getCertificate(alias);

		DOMSignContext dsc = new DOMSignContext(privateKey, doc
				.getDocumentElement());

		KeyInfoFactory kif = signatureFactory.getKeyInfoFactory();
		X509Data x509Data = kif.newX509Data(Collections
				.singletonList(certificate));

		KeyInfo keyInfo = kif.newKeyInfo(Collections
				.singletonList(x509Data));

		XMLSignature signature = signatureFactory.newXMLSignature(
				signedInfo, keyInfo);
		signature.sign(dsc);

		os = new ByteArrayOutputStream();

		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));
	} catch (Exception ex) {
		ex.printStackTrace();
	}
	return os.toString();
}[/code]

#2

conseguimos fazer funcionar aqui. Quem tiver duvidas é só pedir. Estamos pensando em fazer um tutorial pra nfe :-p (se ninguem for contra :-p)


#3

Bah, um tutorial seria muito bacana! Aqui na empresa temos planos para implementar a NFe nos próximos e ter um artigo sobre isso feito por alguém que já teve problemas e conseguiu resolver seria de muita valia! Pois você já tem noção dos problemas encontrados nesse processo.


#4

Um tutorial de NFe seria legal. Eu apoio esta idéia.


#5

Opa,

Conta ai o segredo de tostines...
Como vc conseguiu fazer funcionar?


#6

Consegui terminar os métodos que eu queria. Fiz dois métodos que recebem uma string com o xml e retornam uma String como o xml assinado. O primeiro pega um enviNFe e assina todas as NFe dentro dele. O outro assina o elemento raíz do xml, servindo para o cancelamento e para a inutilização da nota.

aqui vai o método para assinar o enviNFe:

	public static String assinarEnviNFe(String xml) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		// Document docs = builder.parse(new File(
		// "c:/xml/430802017886010001735500000000010000030371-nfe.xml"));
		Document doc = factory.newDocumentBuilder().parse(
				new ByteArrayInputStream(xml.getBytes()));
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
		// Create a Reference to the enveloped document (in this case,
		// you are signing the whole document, so a URI of "" signifies
		// that, and also specify the SHA1 digest algorithm and
		// the ENVELOPED Transform.
		ArrayList transformList = new ArrayList();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED,
				tps);
		Transform c14NTransform = fac.newTransform(
				"http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);
		transformList.add(envelopedTransform);
		transformList.add(c14NTransform);
		// Load the KeyStore and get the signing key and certificate.
		String configName = "/token.cfg";
		Provider p = new sun.security.pkcs11.SunPKCS11(configName);
		Security.addProvider(p);
		char[] pin = { 's', 'a', 'f', 'e', 'w', 'e', 'b' };
		KeyStore ks = KeyStore.getInstance("pkcs11", p);
		ks.load(null, pin);
		KeyStore.PrivateKeyEntry pkEntry = null;
		Enumeration aliasesEnum = ks.aliases();
		PrivateKey privateKey = null;
		while (aliasesEnum.hasMoreElements()) {
			String alias = (String) aliasesEnum.nextElement();
			System.out.println(alias);
			if (ks.isKeyEntry(alias)) {
				pkEntry = (KeyStore.PrivateKeyEntry) ks
						.getEntry(alias, new KeyStore.PasswordProtection(
								"safeweb".toCharArray()));
				privateKey = pkEntry.getPrivateKey();
				break;
			}
		}
		X509Certificate cert = (X509Certificate) pkEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List x509Content = new ArrayList();
		// x509Content.add(cert.getSubjectX500Principal().getName());
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
		for (int i = 0; i < doc.getDocumentElement()
				.getElementsByTagName("NFe").getLength(); i++) {
			assinarNFE(fac, transformList, privateKey, ki, doc, i);
		}
		// Output the resulting document.
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));
		return os.toString();
	}
	private static void assinarNFE(XMLSignatureFactory fac,
			ArrayList transformList, PrivateKey privateKey, KeyInfo ki,
			Document doc, int i) throws Exception {
		// Obtem elemento do documento a ser assinado, será criado uma
		// REFERENCE para o mesmo
		NodeList elements = doc.getElementsByTagName("infNFe");
		Element el = (Element) elements.item(i);
		String id = el.getAttribute("Id");
		// doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// ((Element)
		// doc.getDocumentElement().getElementsByTagName("NFe").item(0))
		// .setAttribute("xmlns", "http://www.portalfiscal.inf.br/nfe");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		Reference ref = fac.newReference("#" + id, fac.newDigestMethod(
				DigestMethod.SHA1, null), transformList, null, null);
		// Create the SignedInfo.
		SignedInfo si = fac
				.newSignedInfo(fac.newCanonicalizationMethod(
						CanonicalizationMethod.INCLUSIVE,
						(C14NMethodParameterSpec) null), fac
						.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
						Collections.singletonList(ref));
		// Create the XMLSignature, but don't sign it yet.
		XMLSignature signature = fac.newXMLSignature(si, ki);
		// Marshal, generate, and sign the enveloped signature.
		// Create a DOMSignContext and specify the RSA PrivateKey and
		// location of the resulting XMLSignature's parent element.
		DOMSignContext dsc = new DOMSignContext(privateKey, doc
				.getDocumentElement().getElementsByTagName("NFe").item(i));
		signature.sign(dsc);
	}

este aqui assina o elemento raiz do xml:

	public static String assinarRaiz(String xml) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		// Document docs = builder.parse(new File(
		// "c:/xml/430802017886010001735500000000010000030371-nfe.xml"));
		Document doc = factory.newDocumentBuilder().parse(
				new ByteArrayInputStream(xml.getBytes()));
		doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// NodeList elements = doc.getElementsByTagName("infNFe");
		Node element = doc.getDocumentElement().getFirstChild()
				.getNextSibling();
		// elements.getLength();
		Element el = (Element) element;
		// Element el =
		// doc.getDocumentElement().getFirstChild().getChildNodes();
		String id = el.getAttribute("Id");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
		// Create a Reference to the enveloped document (in this case,
		// you are signing the whole document, so a URI of "" signifies
		// that, and also specify the SHA1 digest algorithm and
		// the ENVELOPED Transform.
		ArrayList transformList = new ArrayList();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED,
				tps);
		Transform c14NTransform = fac.newTransform(
				"http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);
		transformList.add(envelopedTransform);
		transformList.add(c14NTransform);
		// Load the KeyStore and get the signing key and certificate.
		String configName = "/token.cfg";
		Provider p = new sun.security.pkcs11.SunPKCS11(configName);
		Security.addProvider(p);
		char[] pin = { 's', 'a', 'f', 'e', 'w', 'e', 'b' };
		KeyStore ks = KeyStore.getInstance("pkcs11", p);
		ks.load(null, pin);
		KeyStore.PrivateKeyEntry pkEntry = null;
		Enumeration aliasesEnum = ks.aliases();
		PrivateKey privateKey = null;
		while (aliasesEnum.hasMoreElements()) {
			String alias = (String) aliasesEnum.nextElement();
			System.out.println(alias);
			if (ks.isKeyEntry(alias)) {
				pkEntry = (KeyStore.PrivateKeyEntry) ks
						.getEntry(alias, new KeyStore.PasswordProtection(
								"safeweb".toCharArray()));
				privateKey = pkEntry.getPrivateKey();
				break;
			}
		}
		X509Certificate cert = (X509Certificate) pkEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List x509Content = new ArrayList();
		// x509Content.add(cert.getSubjectX500Principal().getName());
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
		// doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// ((Element)
		// doc.getDocumentElement().getElementsByTagName("NFe").item(0))
		// .setAttribute("xmlns", "http://www.portalfiscal.inf.br/nfe");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		Reference ref = fac.newReference("#" + id, fac.newDigestMethod(
				DigestMethod.SHA1, null), transformList, null, null);
		// Create the SignedInfo.
		SignedInfo si = fac
				.newSignedInfo(fac.newCanonicalizationMethod(
						CanonicalizationMethod.INCLUSIVE,
						(C14NMethodParameterSpec) null), fac
						.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
						Collections.singletonList(ref));
		// Create the XMLSignature, but don't sign it yet.
		XMLSignature signature = fac.newXMLSignature(si, ki);
		// Marshal, generate, and sign the enveloped signature.
		// Create a DOMSignContext and specify the RSA PrivateKey and
		// location of the resulting XMLSignature's parent element.
		DOMSignContext dsc = new DOMSignContext(privateKey, doc
				.getDocumentElement());
		signature.sign(dsc);
		// Output the resulting document.
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));
		return os.toString();
	}

uma coisa que temque cuidar muito é o cabeçalho do xml que temque tá desse jeito

<?xml version="1.0" encoding="UTF-8"?>
<cancNFe versao="1.07" xmlns="http://www.portalfiscal.inf.br/nfe">

ou seja, não pode ter o xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"

o mesmo vale para o enviNFe:

<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.10">
  <idLote>1</idLote> 
  <NFe xmlns="http://www.portalfiscal.inf.br/nfe">

nesse caso tanto o envi como cada nfe devem ter xmlns="http://www.portalfiscal.inf.br/nfe" e o envi não pode ter o xmlns:ns2="http://www.w3.org/2000/09/xmldsig#". Se por acaso o xml estiver do jeito errado, pode usar esses códigos no assinador, ou criar outro método:

esse aqui remove o xmlns:ns2 do elemento raíz:

	doc.getDocumentElement().removeAttribute("xmlns:ns2");

esse aqui adiciona o xmlns necessário a tag NFe:

	((Element) doc.getDocumentElement().getElementsByTagName("NFe").item(i)).setAttribute("xmlns", "http://www.portalfiscal.inf.br/nfe");

Quem quiser verificar o xml pode usar esse site: http://www.sefaz.rs.gov.br/AAE_ROOT/NFE/SAT-WEB-NFE-VAL_1.asp Acho que ele só valida os certificados do Rio Grande do Sul, mas o bom é que ele verifica a estrutura do xml tb.

É isso por enquanto, qualquer coisa é só perguntar.


#7

esqueci de colocar, esse são os imports da classe:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

Estou usando Java 5. então para usar os crypto eu tive que baixar o jwsdp-2.0 (java web server) e importar alguns jars dele. acho que foram esses:

/xmldsig/lib/xmldsig.jar" />
/jaxp/lib/jaxp-api.jar" />
/jaxp/lib/endorsed/dom.jar" />
/jaxp/lib/endorsed/xercesImpl.jar" />
/jwsdp-shared/lib/xmlsec.jar" />
/jaxp/lib/endorsed/xalan.jar" />


#8
 String configName = "/token.cfg";

 Provider p = new sun.security.pkcs11.SunPKCS11(configName);  
 Security.addProvider(p);  
 char[] pin = { 's', 'a', 'f', 'e', 'w', 'e', 'b' };

Com relação ao codigo acima, gostaria de saber sobre esse arq. token.cfg que informação contem nesse arquivo, como faço para gerar esse arquivo ?
e com relação ao char[] pin que informação eu devo setar ?


#9

ale,

Nesse arquivo temos informações sobre o driver do dispositivo pkcs11 instalado.

Segue exemplo:

name = Safenetikey2032

library = c:\windows\system32\dkck201.dll

beleza?


#10

...


#11

Olá,

Estou iniciando com SOAP tbm para um projeto de NFE. Alguém poderiam postar o código que transmite o arquivo após a assinatura?

Muito Obrigado!!


#12

Bom dia pessoal,

Como fica o código acima quando tenho como certificado, um arquivo pfx (serasa)? Como uso o keytool para importar para um keystore e como ficaria o código que busca o certificado?

Orbigado!!!


#13

Boa tarde pessoal,

Estou tentando assinar um XML da NFe usando o código acima, já consegui efetuar a conexão com o web-server usando o código abaixo:

[b]
System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.keyStore", verConf.getPathKeyPFX());
System.setProperty("javax.net.ssl.keyStorePassword", "xxxx");

System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore",verConf.getPathKeyJKS());
[/b]

Alguem já conseguiu assinar um XML NFe usando somente o arquivo .pfx ??


#14

Eu consegui... veja a parte do certificado:

		// Load the KeyStore and get the signing key and certificate.
		KeyStore ks = KeyStore.getInstance(Statics.getKeystoreType());
		FileInputStream fis = new FileInputStream(Statics.getKeystoreFile());
		//load the keystore
		ks.load(fis, Statics.getKeystorePassword().toCharArray());
		String alias = ks.aliases().nextElement();
		KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(Statics.getKeystorePassword().toCharArray()));
		X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List<Serializable> x509Content = new ArrayList<Serializable>();
		x509Content.add(cert.getSubjectX500Principal().getName());
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
		for (int i = 0; i < doc.getDocumentElement().getElementsByTagName("NFe").getLength(); i++) {
			assinarNFE(fac, transformList, keyEntry.getPrivateKey(), ki, doc, i);
		}

So que o retorno da sefaz de MT e o seguinte:

<?xml version="1.0" encoding="UTF-8"?>
<retConsReciNFe xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe retConsReciNFe_v1.10.xsd" versao="1.10">
<tpAmb>2</tpAmb>
<verAplic>1.10</verAplic>
<nRec>510000000060267</nRec>
<cStat>104</cStat>
<xMotivo>Lote processado</xMotivo>
<cUF>51</cUF>
<protNFe versao="1.10">
<infProt>
<tpAmb>2</tpAmb>
<verAplic>1.10</verAplic>
<chNFe>510804926656110128505500012345678918</chNFe>
<dhRecbto>2008-05-05T19:33:00</dhRecbto>
<cStat>297</cStat>
<xMotivo>Rejeicao: Assinatura difere do calculado</xMotivo>
</infProt>
</protNFe>
</retConsReciNFe>

#15

Será que o erro de rejeição tem a ver com encoding, ou algo do sentido?


#16

Bom dia, vc validou seu XMl antes de conectar e enviar??
Acesse esse site e coloque seu XML para testar, ai verificará se ele está correto e se a assinatura está correta antes de conectar no web service.

http://www.sefaz.rs.gov.br/AAE_ROOT/NFE/SAT-WEB-NFE-VAL_1.asp


#17

Bom dia...

Sim, eu validei o schema com um programa chamado XmlNotepad, ele é um schema válido. Segundo informações da sefaz-MT, o esquema está correto, eles dizem que o erro é na assinatura em si.

Quanto aquele validador da sefaz, nao rola pra mim pq a versao que a sefaz-mt usa e diferente...


#18

E o programa Assinador do portal da nfe, aquele vc pode colocar os Schemas da tua versão e ele válida a assinatura, utlizava ele na versão PL005a, PL007..etc..

http://www.nfe.fazenda.gov.br/portal/assinador.aspx

abraços


#19

Eu trabalho com a sefaz-mt e eles estão com a versão 1.10.
Parece que já estão aceitando 1.12 também.


#20

Pessoal, usei o assinador do RS, que usa .net pra assinar, e depois so transmiti com o meu programa em java, dai ele aceita o mardito!!!

Segui o codigo de Assinatura do pessoal aqui no forum, apenas adaptei pra usar um certificado em arquivo, alguem esta passando pelo mesmo ou tem alguma solucao?

Segue abaixo o codigo:

package com.developermaster.nfe.utils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Util {	
	public static String getXmlContent(String xmlFile) {
		String retorno = "";
		try {
			BufferedReader reader = new BufferedReader(new FileReader(xmlFile));
			String aux = null;
			while ((aux = reader.readLine()) != null) {
				retorno += aux;
			}
			reader.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return retorno;
	}
	public static void GravaRetorno(String xmlFile, String conteudo) {
		try {
			FileOutputStream file = new FileOutputStream(xmlFile, false);
			file.write(conteudo.getBytes());
			file.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void ValidateXml(String xml, String xsd) {
		try {
            // Parse an XML document into a DOM tree.
            DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = parser.parse(new File(xml));
            // Create a SchemaFactory capable of understanding WXS schemas.
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            // Load a WXS schema, represented by a Schema instance.
            Source schemaFile = new StreamSource(new File(xsd));
            Schema schema = factory.newSchema(schemaFile);
            // Create a Validator object, which can be used to validate
            // an instance document.
            Validator validator = schema.newValidator();
            // Validate the DOM tree.
            validator.validate(new DOMSource(document));
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
        	e.printStackTrace();
        } catch (IOException e) {
        	e.printStackTrace();
        }
	}
	public static String assinarEnviNFe(String xml) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		factory.setIgnoringElementContentWhitespace(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		// Document docs = builder.parse(new File(
		// "c:/xml/430802017886010001735500000000010000030371-nfe.xml"));
		Document doc = factory.newDocumentBuilder().parse(new File(xml));
		String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance());
		// Create a Reference to the enveloped document (in this case,
		// you are signing the whole document, so a URI of "" signifies
		// that, and also specify the SHA1 digest algorithm and
		// the ENVELOPED Transform.
		ArrayList transformList = new ArrayList();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, tps);
		Transform c14NTransform = fac.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);
		transformList.add(c14NTransform);
		transformList.add(envelopedTransform);
		// Load the KeyStore and get the signing key and certificate.
		KeyStore ks = KeyStore.getInstance(Statics.getKeystoreType());
		FileInputStream fis = new FileInputStream(Statics.getKeystoreFile());
		// load the keystore
		ks.load(fis, Statics.getKeystorePassword().toCharArray());
		KeyStore.PrivateKeyEntry keyEntry = null;
		while (ks.aliases().hasMoreElements()) {
			String alias = ks.aliases().nextElement();
			if (ks.isKeyEntry(alias)) {
				keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(Statics.getKeystorePassword().toCharArray()));
				break;
			}
		}
		X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List x509Content = new ArrayList();
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
		for (int i = 0; i < doc.getDocumentElement()
				.getElementsByTagName("NFe").getLength(); i++) {
			assinarNFE(fac, transformList, keyEntry.getPrivateKey(), ki, doc, i);
		}
		// Output the resulting document.
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));
		return os.toString();
	}
	private static void assinarNFE(XMLSignatureFactory fac,
			ArrayList transformList, PrivateKey privateKey, KeyInfo ki,
			Document doc, int i) throws Exception {
		// Obtem elemento do documento a ser assinado, será criado uma
		// REFERENCE para o mesmo
		NodeList elements = doc.getElementsByTagName("infNFe");
		Element el = (Element) elements.item(i);
		String id = el.getAttribute("Id");
		// doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// ((Element)
		// doc.getDocumentElement().getElementsByTagName("NFe").item(0))
		// .setAttribute("xmlns", "http://www.portalfiscal.inf.br/nfe");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		Reference ref = fac.newReference("#" + id, fac.newDigestMethod(
				DigestMethod.SHA1, null), transformList, null, null);
		// Create the SignedInfo.
		SignedInfo si = fac
				.newSignedInfo(fac.newCanonicalizationMethod(
						CanonicalizationMethod.INCLUSIVE,
						(C14NMethodParameterSpec) null), fac
						.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
						Collections.singletonList(ref));
		// Create the XMLSignature, but don't sign it yet.
		XMLSignature signature = fac.newXMLSignature(si, ki);
		// Marshal, generate, and sign the enveloped signature.
		// Create a DOMSignContext and specify the RSA PrivateKey and
		// location of the resulting XMLSignature's parent element.
		DOMSignContext dsc = new DOMSignContext(privateKey, doc
				.getDocumentElement().getElementsByTagName("NFe").item(i));
		signature.sign(dsc);
	}
	public static String assinarRaiz(String xml) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		//DocumentBuilder builder = factory.newDocumentBuilder();
		// Document docs = builder.parse(new File(
		// "c:/xml/430802017886010001735500000000010000030371-nfe.xml"));
		Document doc = factory.newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));
		doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// NodeList elements = doc.getElementsByTagName("infNFe");
		Node element = doc.getDocumentElement().getFirstChild().getNextSibling();
		// elements.getLength();
		Element el = (Element) element;
		String id = el.getAttribute("Id");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
		// Create a Reference to the enveloped document (in this case,
		// you are signing the whole document, so a URI of "" signifies
		// that, and also specify the SHA1 digest algorithm and
		// the ENVELOPED Transform.
		ArrayList<Transform> transformList = new ArrayList<Transform>();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, tps);
		Transform c14NTransform = fac.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);
		transformList.add(envelopedTransform);
		transformList.add(c14NTransform);
		// Load the KeyStore and get the signing key and certificate.
		KeyStore ks = KeyStore.getInstance(Statics.getKeystoreType());
		FileInputStream fis = new FileInputStream(Statics.getKeystoreFile());
		//load the keystore
		ks.load(fis, Statics.getKeystorePassword().toCharArray());
		String alias = ks.aliases().nextElement();
		KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(Statics.getKeystorePassword().toCharArray()));
		//get the private key for signing.
		//PrivateKey privateKey = (PrivateKey) ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
		X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List<Serializable> x509Content = new ArrayList<Serializable>();
		x509Content.add(cert.getSubjectX500Principal().getName());
		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
		doc.getDocumentElement().removeAttribute("xmlns:ns2");
		// ((Element)
		// doc.getDocumentElement().getElementsByTagName("NFe").item(0))
		// .setAttribute("xmlns", "http://www.portalfiscal.inf.br/nfe");
		// Create a DOM XMLSignatureFactory that will be used to
		// generate the enveloped signature.
		Reference ref = fac.newReference("#" + id, fac.newDigestMethod(
				DigestMethod.SHA1, null), transformList, null, null);
		// Create the SignedInfo.
		SignedInfo si = fac
				.newSignedInfo(fac.newCanonicalizationMethod(
						CanonicalizationMethod.INCLUSIVE,
						(C14NMethodParameterSpec) null), fac
						.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
						Collections.singletonList(ref));
		// Create the XMLSignature, but don't sign it yet.
		XMLSignature signature = fac.newXMLSignature(si, ki);
		// Marshal, generate, and sign the enveloped signature.
		// Create a DOMSignContext and specify the RSA PrivateKey and
		// location of the resulting XMLSignature's parent element.
		DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc
				.getDocumentElement());
		signature.sign(dsc);
		// Output the resulting document.
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));
		return os.toString();
	}
}