Assinatura Digital de XML
Codificação, Segurança & Caracteres
Todo XML fiscal brasileiro — NFe, NFC-e, CT-e, NFS-e nacional — precisa ser assinado digitalmente com o certificado ICP-Brasil (A1 ou A3) do emitente antes de ser transmitido, seguindo o padrão XML Signature (XMLDSig) do W3C. Na prática, o processo tem três passos:
- Calcula-se o hash do conteúdo do elemento a assinar (na NFe, o elemento
infNFe, referenciado pelo seu atributoId) — veja Hash. - Esse hash é criptografado com a chave privada do certificado do emitente — o resultado é a assinatura em si.
- A assinatura, o certificado público correspondente e os metadados do processo ficam embutidos no próprio XML, dentro de uma tag
<Signature>.
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<Reference URI="#NFe35240112345678000199550010000000011000000015">
<DigestValue>base64-do-hash-aqui</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>base64-da-assinatura-aqui</SignatureValue>
<KeyInfo>
<X509Certificate>base64-do-certificado-aqui</X509Certificate>
</KeyInfo>
</Signature>Quem recebe o documento faz o caminho inverso para verificar: recalcula o hash do conteúdo referenciado e confere se bate com o DigestValue; decifra o SignatureValue usando a chave pública contida no certificado (KeyInfo) e confirma que o resultado também bate. Se as duas conferências fecham, o autorizador tem garantia de autoria (só quem tem a chave privada do certificado poderia ter gerado aquela assinatura) e de integridade (o conteúdo não mudou desde que foi assinado).
É exatamente por isso que qualquer alteração no XML depois de assinado — até um espaço em branco a mais ou a reordenação de um atributo — invalida a assinatura: o hash recalculado não bate mais com o DigestValue original. Na prática, isso significa nunca "bonito-imprimir" (reformatar) ou editar manualmente um XML já assinado, e sempre bater a codificação antes de assinar — mudar o encoding depois também muda os bytes, e por consequência o hash.