Assinar NFe com JAXB

Salve galera,

Seguinte, peguei os XSD`s da receita e usei o JAXB para gerar as classes.
Estou preenchendo os meus beans da NFe e depois eu converto eles em XML para assinar. Uso o codigo abaixo:

   public String transformaTEnviNFeEmXML(TEnviNFe enviNFe) throws JAXBException {
        StringWriter writer = new StringWriter();
        JAXBContext context = JAXBContext.newInstance("br.com.ces.xsd.versao20.enviNFe");
        Marshaller marshaller = context.createMarshaller();
        JAXBElement<TEnviNFe> element = new ObjectFactory().createEnviNFe(enviNFe);

        marshaller.marshal(element, writer);
        String s = writer.getBuffer().toString();
        return s;
    }

Ai assino o meu XML, ate ai blza.
So que estou tentando fazer o reverso, que é pegar o XML assinado e converter ele para o meu Bean e enviar o mesmo para a receita.
Utilizando o codigo abaixo, todos os atributos do meu bean esta sendo preenchido, somente a parte de assinatura que nao esta sendo carregada. Esta ficando null.

 public  TEnviNFe transformaXMLEmTEnvi(String xml) throws JAXBException {
        StringReader stringReader = new StringReader(xml);
        JAXBContext context = JAXBContext.newInstance("br.com.ces.xsd.versao20.enviNFe");
        Unmarshaller unmarshaller = context.createUnmarshaller();
        JAXBElement<TEnviNFe> element = (JAXBElement<TEnviNFe>) unmarshaller.unmarshal(stringReader);
        TEnviNFe tEnviNFe = element.getValue();
        return tEnviNFe;
    }

Alguem sabe onde estou errado?

Alguem!!!

O Brother e que vc deve assinar cada nfe no xml envNFe.Tenho um metodo aqui para
isto,mas comigo ta dando um erro.

 IOException: toDerInputStream rejects tag type 60
        at sun.security.util.DerValue.toDerInputStream(DerValue.java:806)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1201)

Testa ai que sabe vc ate me ajuda, a logica deste metodo e no xml envNFe ele faz um loop em todas as NFe e assina.

public static String assinarEnviNFe(String xml, String senha) 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 = builder.parse(new File(xml));

        // 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.
        KeyStore ks = KeyStore.getInstance("PKCS12");     //MUDEI AQUI PRA PEGAR DIRETO O PFX
       // FileInputStream fis = new FileInputStream(xml);
        //load the keystore
        ks.load(new FileInputStream(xml), senha.toCharArray());
        String alias = ks.aliases().nextElement();

        KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(senha.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);
        }
        // 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 codigo eu peguei aqui mesmo .

Eai mano, deu certo?

Estou na mesma situação… :?

Fiz assim e deu certo, Graças a Deus!!!

Primeiro: pego o meu Objeto NFe e tranformo ele em um XML.
Segundo: Assino o meu XML normalmente.
Terceiro: Transformo novamente o meu XML em Objeto NFe, nesse ponto estava dando erro. Ai fiz da seguinte maneira abaixo e deu certo.

  JAXBContext context = JAXBContext.newInstance("br.com.teste.nfe");
  Unmarshaller unmarshaller = context.createUnmarshaller();
  File notaFile = new File("C:/temp/NOTA.xml");
 TNFe nfe = unmarshaller.unmarshal( new StreamSource(notaFile), TNFe.class ).getValue();
//Meu objeto nfe agra esta vindo com a assinatura

Agora galera esta dando esse problema
http://www.guj.com.br/posts/list/214968.java#1095578

Galara, desculpas por não ter respondido antes, não recebi email informando que o topico foi modificado!!!

Eu acabei fazendo no braço mesmo, com XPath.
Serializei, assinei e fiz o parse do XML pegando somente a assinatura.

Boa tarde vcsmetallica.

Como voce resolveu o seu problema?
Eu segui os seus exemplos, mas o meu objeto TNfe ainda está com a signature = null. Os outros atributos estão sendo carregados.

   public String transformaTEnviNFeEmXML(TNFe tNFe) throws JAXBException {
        StringWriter writer = new StringWriter();
        JAXBContext context = JAXBContext.newInstance("br.com.flysolution.nfe2.enviolote");
        Marshaller marshaller = context.createMarshaller();
        TNFe element = new ObjectFactory().createTNFe(tNFe);
        marshaller.marshal(element, writer);
        String s = writer.getBuffer().toString();
        return s;
    }

    public TNFe transformaXMLEmTEnvi(String xml) throws JAXBException {
        int inicio = xml.indexOf("<NFe xmlns");
        int tamanhoStr = xml.length();
        xml = xml.substring(inicio, tamanhoStr);
        System.out.println(xml);
        JAXBContext context = JAXBContext.newInstance("br.com.flysolution.nfe2.enviolote");
        Unmarshaller unmarshaller = context.createUnmarshaller();
        File notaFile = new File("/home/francisco/testeLoteSign.xml");
        TNFe tNFe = unmarshaller.unmarshal(new StreamSource(notaFile), TNFe.class).getValue();
        return tNFe;
    }

Se puder ajudar. Obrigado.

Edifran,

Resolvi de uma maneira simples: usei o Axis, abandoinei a causa do JAXB.

Att

vcsmetallica

Pessoal,

Não sei se é assim mesmo, mas a minha mensagem SOAP de envio está ficando assim:

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
    <S:Header>
        <nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">
            <cUF>35</cUF>
            <versaoDados>2.00</versaoDados>
        </nfeCabecMsg>
    </S:Header>
    <S:Body>
        <nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">
            <enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
                <idLote>1</idLote>
                <NFe xmlns="http://www.portalfiscal.inf.br/nfe">
                    <infNFe
...
...
...
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <ns2:SignedInfo>
       <ns2:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
...
...
...

Percebam que tanto no cabeçalho quanto no Dados existe um atributo a mais.

xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"

Não sei se é pelo fato dessa tag a mais, que as tags referentes a assinatura, todas estão com esse ns2:
Já não sei o que pode estar acontecendo, to mexendo num monte de coisa no código, mas sem sucesso. Se alguém puder dar uma dica, obrigado.

vcsmetallica, valeu a dica, mas eu não posso mudar pra axis, porque já temos coisas em JAXB, e no começo tivemos alguns problemas mesmo com axis. Então optamos pelo JAXB.
O problema da assinatura vim com null no objeto TNfe, foi resolvido, mas apareceu este que estou citando agora.

Edifran,

Quando usei o JAXB realizei todos os passos que havia de seguir. Quando eu envio para a receita vai normalmente, o retorno da receita que retornava um erro doidao.
Abaixo os procedimentos que eu seguia:

Com o XML assinado eu uso o seguinte comando:

TNFe nfe = montaXML.trasnformaXML(xml);
TEnviNFe enviNFe = new ObjectFactory().createTEnviNFe();
enviNFe.getNFe().add(nfe);
enviNFe.setIdLote(usuario.getIdLote());
enviNFe.setVersao(ConstantePadrao.VERSAO_ENVIO_NFE);
 public TNFe trasnformaXML(String xmlAssinado) throws NfeException {
        try {
            StringReader reader = new StringReader(xmlAssinado);
            JAXBContext context = JAXBContext.newInstance("br.com.nfe.xsd.versao20.enviNFe");
            Unmarshaller unmarshaller = context.createUnmarshaller();
            TNFe nfe = unmarshaller.unmarshal(new StreamSource(reader), TNFe.class).getValue();
            return nfe;
        } catch (JAXBException ex) {
            throw new NfeException(ex);
        }
    }

e na hora de enviar usava o seguinte comandos:


                NfeRecepcao2Soap12 nfeRecepcao2Soap12 = new NfeRecepcao2().getNfeRecepcao2Soap12();
                NfeDadosMsg dadosMsg = new NfeDadosMsg();
                dadosMsg.getContent().add(enviNFe);
                Holder<NfeCabecMsg> nfeCabecMsg = new Holder<NfeCabecMsg>(createNfeCabecMsg());
                NfeRecepcaoLote2Result result = nfeRecepcao2Soap12.nfeRecepcaoLote2(dadosMsg, nfeCabecMsg);
                List<Object> lista = result.getContent();
                for (Object object : lista) {
                    File fileTemp = NFeUtil.gerarArquivoTemporario();
                    ElementNSImpl elementNSImpl = (ElementNSImpl) object;
                    NFeUtil.transformarObjetoElementNSImpToXML(elementNSImpl, fileTemp);
                    xmlRetorno = NFeUtil.passarUmXmlParaString(fileTemp);
                }

Estou passando por um problema e acredito que seja exatamente o mesmo comentado aqui. Eu tenho o XML da nota assinada e enviada e estou tentando converter no objeto TEnviNfe. Ao passar pelo unmarshaller o objeto TNfe está com a parte signature com valor null. Alguém sabe qual o problema que pode estar ocorrendo? Vi em outros posts pessoas comentando o mesmo problema mas não vi ninguém que tenha solucionado.

Ninguém?

igorantonioandrade, vcsmetallica, edifran,

como vcs estao com o processo da nota?, estou convertendo para usar com jaxb porem o que esta acontecendo. gero xml (nota.xml) do tipo NFe com assinatura, tudo ok.

pode quando eu leio o xml para montar enviNFe com jaxb o sw vem na tag <ns2:Signature> se puderem me ajudar

            TEnviNFe enviNFe = new TEnviNFe();
            enviNFe.setIdLote(nroLote);
            enviNFe.setIndSinc(&quot;0&quot;);
            enviNFe.setVersao(&quot;3.10&quot;);

            enviNFe.getNFe().add(nfe);
            JAXBContext context = JAXBContext.newInstance(TEnviNFe.class);
            Marshaller marshaller = context.createMarshaller();

            StringWriter sw = new StringWriter();
            
            marshaller.marshal(enviNFe, sw);
            System.out.println(sw);
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;NFe xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"&gt;
  &lt;infNFe Id="NFe431405XXXXXXXXXXXXXX550000000007231000170510" versao="3.10"&gt;...&lt;/infNFe&gt;
  &lt;ns2:Signature&gt;
    &lt;ns2:SignedInfo&gt;
      &lt;ns2:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
      &lt;ns2:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
      &lt;ns2:Reference URI="#NFe431405XXXXXXXXXXXXXX550000000007231000170510"&gt;
        &lt;ns2:Transforms&gt;
          &lt;ns2:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/&gt;
          &lt;ns2:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
        &lt;/ns2:Transforms&gt;
        &lt;ns2:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
        &lt;ns2:DigestValue&gt;...&lt;/ns2:DigestValue&gt;
      &lt;/ns2:Reference&gt;
    &lt;/ns2:SignedInfo&gt;
    &lt;ns2:SignatureValue&gt;...&lt;/ns2:SignatureValue&gt;
    &lt;ns2:KeyInfo&gt;
      &lt;ns2:X509Data&gt;
        &lt;ns2:X509Certificate&gt;...&lt;/ns2:X509Certificate&gt;
      &lt;/ns2:X509Data&gt;
    &lt;/ns2:KeyInfo&gt;
  &lt;/ns2:Signature&gt;
&lt;/NFe&gt;

Não entendi seu problema bruxel. Pode explicar melhor?

igorantonioandrade, vamos ver consigo lhe simular,

tenho um xml assinado do tipo NFe, esta perfeito é valido assinado e tudo mais.

agora o que preciso fazer eh pegar este xml, ler ele com JAXB e transformar em um TEnviNFe para enviar para a receito, ate aqui tudo bem.

porem ao converter com o JAXB o TEnviNFe me aparece os maltidos ns2 e algumas outras coisas que estao fazendo a assinatura ser invalida.

basicamente eh pegar um tnfe.xml e transforma-lo num tenvinfe.xml com JAXB