A assinatura tem que ser incluida como um nó filho do elemento NFe, no mesmo nível do nó infNFe, conforme mostrado no excerto de XML de Nota Fiscal abaixo:
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe versao="1.10" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
<infNFe Id="NFe3508059978"versao="1.10">
<cUF>35</cUF>
<cNF>518005127</cNF>
<natOp>Venda a vista</natOp>
<mod>55</mod>
<serie>1</serie>
<dEmi>2008-05-06</dEmi>
<tpAmb>2</tpAmb>
</infNFe>
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe3508059978"
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>4aXU7m8rl14ALy6X...=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>Igq7eI/Fy3PyjjSW...=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIGxDCCBaygAwIBAgIIN6q4...=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</NFe>
</enviNFe>
<enviNFe versao="1.10" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
<infNFe Id="NFe3508059978"versao="1.10">
<cUF>35</cUF>
<cNF>518005127</cNF>
<natOp>Venda a vista</natOp>
<mod>55</mod>
<serie>1</serie>
<dEmi>2008-05-06</dEmi>
<tpAmb>2</tpAmb>
</infNFe>
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe3508059978"
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>4aXU7m8rl14ALy6X...=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>Igq7eI/Fy3PyjjSW...=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIGxDCCBaygAwIBAgIIN6q4...=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</NFe>
</enviNFe>
Considere a variável xmlNFe do tipo XmlElement criada de acordo com o descrito no post sobre criação de nós no XML. Considere também uma instância da classe SignedXml chamada signedXml e preparada da forma descrita no post sobre assinatura de um Xml. Vou usá-las no exemplo a seguir.
Primeiro, criarei um nó para conter o elemento Signature. Depois, vou usar as propriedades SignedInfo e KeyInfo do signedXml para obter nós XML contendo respectivamente dados sobre a informação que foi assinada e sobre a chave usada nessa assinatura:
XmlElement xmlSignature = doc.CreateElement("Signature", "http://www.w3.org/2000/09/xmldsig#");
XmlElement xmlSignedInfo = signedXml.SignedInfo.GetXml();
XmlElement xmlKeyInfo = signedXml.KeyInfo.GetXml();
XmlElement xmlSignedInfo = signedXml.SignedInfo.GetXml();
XmlElement xmlKeyInfo = signedXml.KeyInfo.GetXml();
Note que o namespace passado para a criação do nó Signature é diferente daquele usado para criar as informações da Receita Federal que usei no post sobre a criação de nós. O namespace "http://www.w3.org/2000/09/xmldsig#" indica que vamos usar a sintaxe de assinatura descrita no link do W3C, conforme especificado na documentação da Receita Federal.
Além dos dados que já obtivemos, é necessário ainda acrescentar a assinatura em si como nó filho do elemento Signature. De acordo com a documentação, a assinatura - que é uma sequência de bytes - deve ser representada como um texto utilizando a codificação Base 64. A criação do nó SignatureValue, sua conversão para Base 64 e a adição do nó ao elemento Signature estão no trecho de código abaixo:
XmlElement xmlSignatureValue = doc.CreateElement("SignatureValue", xmlSignature.NamespaceURI);
string signBase64 = Convert.ToBase64String(signedXml.Signature.SignatureValue);
XmlText text = doc.CreateTextNode(signBase64);
xmlSignatureValue.AppendChild(text);
xmlSignature.AppendChild(xmlSignatureValue);
string signBase64 = Convert.ToBase64String(signedXml.Signature.SignatureValue);
XmlText text = doc.CreateTextNode(signBase64);
xmlSignatureValue.AppendChild(text);
xmlSignature.AppendChild(xmlSignatureValue);
O trecho signedXml.Signature.SignatureValue é onde se recupera o valor da assinatura computada.
Agora, só falta importar os dados contidos nos elementos xmlSignedInfo e xmlKeyInfo obtidos no primeiro passo, acrescentado-os ao elemento NFe:
xmlSignature.AppendChild(doc.ImportNode(xmlSignedInfo, true));
xmlSignature.AppendChild (doc.ImportNode(xmlKeyInfo, true));
xmlNfe.AppendChild(xmlSignature);
xmlSignature.AppendChild (doc.ImportNode(xmlKeyInfo, true));
xmlNfe.AppendChild(xmlSignature);
Depois de acrescentar o xmlNfe ao documento XML final, deve-se transformar o XmlDocument doc em texto para ser enviado à Receita Federal.
2 comentários :
Muito bom prof.
Entretanto, como faria para assinar uma string ?
Diferente da NF-e a NFS-e difere da forma de assinar. Por exemplo, para SP a assinatura se faz sobre uma string repassada. Voce tem alguma sugestão ?
Giordani Rocha
Giordani
Dê uma olhada nas outras classes do namespace System.Security.Cryptography. Por exemplo, a classe RSAPKCS1SignatureFormatter permite criar a assinatura RSA PKCS #1 para um array de bytes que você fornece.
Postar um comentário
OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.
Observação: somente um membro deste blog pode postar um comentário.