Validando a Assinatura Digital da NF-e


Atualmente as empresas emitem as notas fiscais em formato eletrônico. Para isso, foi desenvolvido um projeto que especifica e rege a emissão destas notas em ambiente nacional, que é conhecido como Nota Fiscal Eletrônica ou, simplesmente, NF-e. Este projeto faz uso de diversas tecnologias para garantir a segurança e, principalmente, a integridade da mesma.

A integridade é a garantia de que o arquivo XML que a representa não tenha sido alterado desde a sua emissão. Quando uma empresa emite uma nota fiscal, a SEFAZ gera um arquivo XML digitalmente assinado, utilizando o certificado digital da empresa emitente. Como sabemos, esse arquivo XML é a nota fiscal em formato eletrônico, e essa assinatura está embutida nele. A assinatura digital nada mais é que um cálculo matemático que é realizado sobre todo o arquivo XML, e se qualquer mudança ocorrer neste depois da assinatura, a mesma se tornará inválida.

Se você recebe este arquivo e quer garantir que ele não tenha sido alterado, então podemos recorrer à classes que estão dentro do .NET Framework para realizar esta validação. Basicamente devemos carregar o conteúdo XML para o objeto XmlDocument, e em seguida, procurar pelo elemento <Signature /> que é armazena o hash calculado e o certificado serializado que foi utilizado para realizar a assinatura.

var xml = new XmlDocument();
xml.Load(“00000000000000000000000000000000000000000000.xml”);

var nfe = (XmlElement)xml.GetElementsByTagName(“NFe”)[0];
var signature = (XmlElement)nfe.GetElementsByTagName(“Signature”)[0];
var signer = new SignedXml();

signer.LoadXml(signature);
Console.WriteLine(signer.CheckSignature());

Depois de carregado e separado os elementos que serão avaliados, recorrermos a classe SignedXml para validar a assinatura, onde devemos submeter o elemento que contém a assinatura para o método LoadXml, e em seguida, invocar o método CheckSignature, que retorna um valor boleano indicando se ela está ou não válida.

O overload do método CheckSignature utilizado acima (sem parâmetros) analisa o elemento <Signature /> tentando extrair os certificados de forma automática. Caso queira ter um maior controle sobre os certificados utilizados para analisar a assinatura, podemos utilizar um código mais rebuscado para atingir este objetivo:

private static bool ValidateWithCertificate(SignedXml signer)
{
    var keyInfoEnumerator = signer.KeyInfo.GetEnumerator();

    while (keyInfoEnumerator.MoveNext())
    {
        var x509Data = keyInfoEnumerator.Current as KeyInfoX509Data;

        if (x509Data != null && x509Data.Certificates.Count > 0)
            foreach (var cert in x509Data.Certificates)
                if (signer.CheckSignature((X509Certificate2)cert, true))
                    return true;
    }

    return false;
}

Como o próprio nome sugere, a propriedade KeyInfo contém informações referentes à chave que foi utilizada para realizar a assinatura. E, utilizando um enumerador, identificamos se trata-se de um certificado, e ao iterar pela coleção, invocamos o método CheckSignature, e através de um segundo overload, passamos o certificado que queremos que ele considere para realizer a validação. Apesar de ter o mesmo resultado, aqui é possível extrair informações do certificado utilizado, caso seja necessário.

Importante: um erro bastante comum é que alguns sistemas incluem novas informações no XML depois que ele foi assinado. Ao fazer isso, a assinatura digital é corrompida, e ao submetermos o XML para o código que escrevemos acima, a assinatura será dada como inválida. Entre essas informações, é comum ver namespaces como os que são mostrados abaixo (em negrito), e segundo a Nota Técnica 2010/009 da SEFAZ, eles não devem ser incluídos, nem antes, e muito menos depois, da assinatura.

<?xml version=”1.0″ encoding=”UTF-8″?>
<nfeProc xmlns=”http://www.portalfiscal.inf.br/nfe&#8221;
         xmlns:ds=”http://www.w3.org/2000/09/xmldsig#&#8221;
         xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

         versao=”2.00″>
  <NFe xmlns=”http://www.portalfiscal.inf.br/nfe”&gt;
    <infNFe Id=”NFe…” versao=”2.00″>

Publicidade

4 comentários sobre “Validando a Assinatura Digital da NF-e

  1. Acho que lá no início isso seria o suficiente:

    var signature = xml.Descendents("Signature").First() ;

  2. Boas Vitor,

    Repare que estou utilizando o – antigo – XmlDocument e XmlElement (DOM), que não são, nativamente, "LINQ To XML friendly". Por mais que existam algumas alternativas para fazer a conversão entre elas, o SignedXml também lida diretamente com as classes Xml*.

    Sendo assim, optei por recorrer ao que estas classes disponibilizam sem fazer a tal conversão.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s