13.1. Assinatura XML
13.1.1. Assinar
13.1. Assinatura XML
« Anterior
13.1.2. Assinar NFC-e
Próximo »

13.1.1. Assinar

Assinatura Digital XML no padrão do Projeto NF-e

Assinatura

string Assinar(string XMLString, string RefUri, string NomeCertificado, out int resultado, out string msgResultado)

Descrição:

Funcionalidade para realizar a assinatura digital no padrão XML Digital Signature enveloped em um documento XML.

A assinatura é realizada na tag informada no parâmetro RefUri do XML existente no conteúdo do parâmetro: XMLString.

É necessário informar o certificado digital que será utilizado para assinatura no parâmetro NomeCertificado.

A DLL oferece 3 forma de uso do certificado digital:

1. uso de certificado digital existente no repositório MY do CSP do usuário corrente (currentuser)

É a forma de mais comum de uso, cabe ressaltar que é a única forma de uso de certificado digital do tipo A3 que a DLL oferece.
O usuário deve passar como parâmetro o campo assunto do certificado no parâmetro NomeCertificado para que a DLL localize um certificado digital com mesmo assunto no repositório MY do currentuser do equipamento.
Esta forma de uso requer a prévia instalação do certificado digital na conta do usuário do Windows (logon) que irá utilizar o certificado digital.

2. uso de certificado digital em arquivo no formato pfx

Permite o de uso de certificado digital em arquivo formato pfx.
O caminho da localização (path) do arquivo pfx deve ser passado para a DLL no formato: ARQUIVO | [nome do arquivo pfx com caminho completo] | [senha do arquivo] no parâmetro NomeCertificado, ex.: "ARQUIVO|c:\certificado.pfx|senha".
Esta opção só funciona com certificado digital do tipo A1.

3. uso de certificado digital em string base64

Permite uso o arquivo do certificado digital em formato pfx convertido em uma string base64. O certificado digital em string base64 deve ser passado para a DLL no formato: CERTIFICADO | [string base64 do arquivo pfx] | [senha do arquivo] no parâmetro NomeCertificado, ex.: "CERTIFICADO|MIIGoDCCBYigAwIBAgIQep(arquivo pfx do certificado digital convertido em base64...)QQDExNBQy|senha".
Esta opção só funciona com certificado digital do tipo A1. É uma opção de uso que oferece maior versatilidade, pois permite o armazenamento do certificado digital em banco de dados na aplicação. É a forma mais indicada para uso em ASP.NET.

Validade do Certificado Digital

A DLL só trabalha com certificados digitais que estão dentro do período de validade. Assim, os certificados digitais que não se encontram dentro do período de validade não serão utilizados. Algumas AC emitem certificados digitais com data de início de validade futura, neste caso o certificado digital só vai ser mostrado a partir da data e hora que constar como data de início de validade, da mesma forma os certificados digitais expirados não serão mostrados.

Repositório de Certificado Digital

A DLL pesquisa o repositório de certificados digitais do usuário corrente, isto é, somente os certificados digitais instalados no repositório de certificados digitais do logon do usuário estarão disponíveis. Caso a aplicação seja um serviço windows ou seja executada como um serviço (aplicação ASP), pode ser necessária a instalação do certificado digital no repositório local machine e uma versão diferente da DLL.

Certificado Digital com chave privada

Quando falamos de certificado digital válido, estamos falando de um certificado digital com chave privada. Já aconteceu do desenvolvedor receber o certificado digital do cliente, que mesmo após a instalação não aparecia no repositório de certificados digitais por não possuir a chave privada. A chave pública do certificado digital não tem a chave privada e geralmente tem a extensão cer, assim caso receba um arquivo com esta extensão, existe uma grande possibilidade de ser uma chave pública que não serve para autenticar e nem para assinatura digital.

Também é possível verificar se o certificado digital tem chave privada ou não pela sua propriedade na opção Ferramentas/Opções da Internet/Conteúdo/Certificados/Exibir do menu do Internet Explorer:

ExemploCertificado

Parâmetros:

nome tipo fluxo descrição
XMLString string entrada informar uma string com o XML que será assinado.
RefUri string entrada informar a tag que será assinada (Ex. infNFe para NFe, infDPEC para DPEC, etc.) com a referência da URI a ser assinada.
NomeCertificado string entrada informar o certificado digital que será utilizado para assinatura:
1. informar o assunto do certificado digital que deve existir no repositório MY do current user, ex.: "CN=NFe - Associacao NF-e:99999090910270, C=BR, L=PORTO ALEGRE, O=Teste Projeto NFe RS, OU=Teste Projeto NFe RS, S=RS".
2. informar: ARQUIVO | [nome do arquivo pfx com caminho completo] | [senha do arquivo] para uso do certificado digital em arquivo pfx, ex.: "ARQUIVO|c:\certificado.pfx|senha".
3. informar: CERTIFICADO | [string base64 do arquivo pfx] | [senha do arquivo] no parâmetro NomeCertificado para passar uma string contendo um certificado digital em base64, ex.:"CERTIFICADO|MIIGoDCCBYigAwIBAgIQep(arquivo pfx do certificado digital convertido em base64...)QQDExNBQy|senha".
resultado inteiro saída retorna o código do resultado da chamada da DLL
msgResultado string saída retorna a literal do resultado da chamada da DLL

Retorno:

O resultado da chamada da assinatura é uma string com o XML assinado.

Integridade da Assinatura Digital

A assinatura digital é o resultado da aplicação de critografia assimétrica no resumo da mensagem (message digest) com a chave privada do assinante. Qualquer alteração do conteúdo do XML da NF-e tem reflexo no resumo da mensagem e invalida a assinatura digital. A DLL elimina todos os espaços em branco e outros caracteres de formatação como tab/CR/LF do XML da NF-e antes de aplicar a assinatura digital, assim o arquivo XML assinado não deve ser modificado em nenhuma hipótese para não invalidar a assinatura digital.

Outras causas que comprometem a validade da assinatura digital

O projeto da assinatua digital prevê que os arquivos XML utilizem a codificação UTF-8. A maioria das aplicações trabalham com a codificação ANSI que tem divergência na representação dos caracteres especiais (Ex. Ç, º, Á, etc). A forma mais simples de evitar os reflexos do uso de caracteres especiais é vedar a sua utilização como faz o aplicativo emissor de NF-e de SP, existem UF que não aceitam caracteres especiais como é o caso do MT. Em geral, o problema acontece quando o destinatário da NF-e tenta importar o arquivo XML da NF-e no aplicativo visualizador da RFB e o provedor de solução é acionado que aciona o nosso suporte... Conhecendo estas particularidades é possível conviver com os caracteres especiais, o problema todo está na fase que o XML é gerado em arquivo, como já dito as aplicações trabalham em uma codificação diferente do UTF-8 e gravamos o arquivo sem alterar a codificação e o arquivo XML tem a declaração XML no início do arquivo onde dizemos que estamos adotando a codificação UTF-8. A codificação ANSI e UTF-8 é igual até o caractere 127, os caracteres especias tem codificação diferente, por exemplo o caractere º tem representação diferente no ANSI (ba em hexadecimal) e no UTF-8 (c2 ba em hexadecimal), o grande problema é que o UTF-8 é multibyte e alguns caracteres são representados com 2, 3 ou 4 bytes e neste processo pode ocorrer o acréscimo de algum byte com reflexo na assinatura digital.

Caractere símbolo código ANSI (hexadecimal) código UTF-8 (hexadecimal)
símbolo de numeral º ba c2 ba
A com til à c3 c3 83
a com til ã e3 c3 a3
cecedilha minúsculo ç e7 c3 A7
cecedilha maiúsculo Ç c7 c3 87

Para evitar este tipo de problema, basta fazer a conversão da codificação de ANSI para UTF-8 na string antes da gravação do arquivo XML, para outros detalhes vide o post: Distribuição da NF-e para o Destinatário.

Obs: A aplicação da conversão da codificação só deve ser feita de ANSI para UTF-8, se a string já estiver em UTF-8 a aplicação da conversão vai corromper o conteúdo da string!

Assinatura de NF-e em uma estrutura de lote

A DLL não permite a assinatura de uma NF-e contida em uma estrutura de lote de NF-e, assim, a assinatura da NF-e deve ser realizada individualmente.

O uso de namespaces

A tag raiz do XML deve ter o namespace do projeto (xmlns="http://www.portalfiscal.inf.br/nfe") e nada mais, evite o uso de outros namespaces, pois apesar de aceitos em algumas UF, podem causar falhas na validação da assinatura digital.

Exemplo de uso de namespace recomendado: <NFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">

PRETENDO FAZER O ENVIO DE UMA NF-e POR VEZ

Muitas empresas emitem uma pequena quantidade notas fiscais durante o dia, não justificando a formação de lote de NF-e para envio à SEFAZ. A DLL oferece uma opção de envio individual de NF-e que não requer que a NF-e esteja assinada, pois a funcionalidade de envio valida o schema XML, assina a NF-e, monta o lote e faz a transmissão. Assim, não assine a NF-e caso pretenda utilizar a funcionalidade de envio individual de NF-e.

Armazenamento da NF-e

Recomendamos fortemente que grave o arquivo XML assinado, pois ele poderá ser útil no futuro em caso de algum problema. Não converta a string do XML assinado em UTF-8, pois este processo altera a codificação dos caracteres especiais para a codificação UTF-8 e muitos usuários importam arquivo convertido em UTF-8 para a aplicação sem converter a string lida para ANSI que é a codificação padrão de muitos ambientes de programação e acabam corrompendo o arquivo sem perceber.

O usuário deve arquivar o XML da NF-e assinado da forma que entender mais conveniente, como por exemplo:
. campo tipo blob do BD;
. arquivo no file system.

Também é conveniente que exista alguma forma simples e automática de armazenamento de segurança, como por exemplo:
. envio do arquivo via e-mail para uma conta de e-mail do tipo gmail;
. uso de disco virtual do tipo dropbox.

O resultado da assinatura é o código numérico devolvido no parâmetro resultado com os seguintes significados:

código Mensagem origem regra
5300 Assinatura realizada com sucesso DLL -
5301 Erro: Certificado digital inexistente para [nome informado], verifique se o Assunto (subject name) está correto), ou talvez o certificado digital esteja fora do prazo de validade ou não esteja instalado para o usuário.. DLL -
5302 Erro: A tag de assinatura [nome da tag informada para a DLL] inexiste, verifique o nome da tag informada, Ex. de tag válida: infNFe DLL -
5303 Erro: A tag de assinatura [nome da tag informada para a DLL] não é unica, a assinatura deve ser realizada em uma NF-e, a NF-e deve ser inserida no lote somente após o processo de assinatura. DLL -
5304 Erro: Tentativa de assinar uma NF-e contida em um lote, a assinatura deve ser realizada em uma NF-e fora do lote, devendo ser inserida no lote somente após o processo de assinatura. DLL -
5305 Erro: Falha no acesso ao XML, XML mal formado ou XML vazio: [mensagem de erro] DLL -
5306 Erro: Falha no acesso do certificado digital: [mensagem de ERRO DO WINDOWS] DLL -
5307 Erro: Falha na Assinatura: [mensagem do ERRO DO WINDOWS] - vide guia de uso da DLL - https://www.flexdocs.net/guiaNFe/FAQ.assinatura.html DLL -
5403 Erro: Falha ao acessar certificado digital [mensagem de ERRO DO WINDOWS] DLL -
5404 Erro: Nenhum certificado digital selecionado DLL
5405 Erro: Nenhum certificado válido foi encontrado com o nome [NomeCertificado] informado no repositório [MY do CurrentUser] DLL -
5406 Erro: Falha no tratamento do parâmetro nome: [nome informado] DLL -
5407 Erro: Quantidade de parâmetos inválido: [nome informado] DLL -
5408 Erro: Falha na criação do objeto certificate: [mensagem do ERRO DO WINDOWS] DLL -

5307 - Falha na Assinatura: [mensagem do ERRO DO WINDOWS]

O Erro 5307 é uma falha do certificado digital, ele pode não ter sido corretamente instalado ou não estar disponível para uso se for um token ou smart card.

A DLL acessa os certificados digitais existentes no provedor de certificados digitais (CSP) do Windows do usuário corrente (o que está logado no equipamento), desta forma para a DLL é indiferente se o certificado digital é do tipo A1 ou A3, desde que o certificado digital esteja corretamente instalado no CSP do Windows.

Assim, o problema de incompatibilidade do certificado digital ou do hardware criptográfico (smartcard/token) é com o framework .NET do Windows e não tem relação com a DLL, todas as aplicações que utilizam o framework .NET (Ex.: assinador da SEFAZ/RS) terão problema para usar o certificado digital se ele não for compatível com o Windows e não oferecer suporte necessário para o .NET Framework acessar a funcionalidade de cálculo de hash e criptográfia.

Compatibilidade do Certificado Digital com a versão do Windows

O usuário deve verificar se o smartcard/token adquirido é compatível com a versão do Windows e não tem incompatibilidade na assinatura XML com uso do framework .NET 2.0.

Teste do Certificado Digital

Os testes que são realizados pelo atendimento do fornecedor do certificado digital, em geral, limita-se a testar funcionalidade autenticação do usuário no e-CAC em algum outro Portal que exige autenticação mútua com envio do certificado digital e não faz o teste de assinatura digital XML que é a causa do Erro 5307.

Utilize aplicativos que utilizam o framework .NET 2.00, como por exemplo o assinador da SEFAZ/RS para ter uma segunda opinão. Uma aplicação que utiliza a biblioteca CAPICOM não serve de parâmetro para comparação.

Solução do problema

Desinstale o certificado digital e instale novamente conforme instruções do fornecedor do certificado digital.

Certificado Digital A1

A instalação de um certificado digital do tipo A1 requer o arquivo pfx (o arquivo com extensão cer não tem chave privada). Arquivos com extensão cer são arquivos de chave pública do certificado digital e não servem para uso em assinatura digital.

Certificado Digital A3

Se for um dispositivo A3 (token/smart card) verifique se os drivers e gerenciador criptográfico do seu dispositivo são compatíveis com a versão do Windows em uso.

  • drivers/gerenciadores para TOKEN

  • drivers/gerenciadores para SMARTCARD

    O fornecedor do dispositivo também deve ser consultado para obter os drivers e gerenciadores corretos.

Certificado Digital CEF - CAIXA

Veja uma possível solução para certificado digital da CEF - CAIXA.

Histórico de atualização:

Exemplos:

Visual Basic

 
' declaração das variáveis que serão utilizadas na passagem de parâmetros da DLL
'
Dim XMLString As String     ' informar o xml a ser assinado
Dim RefUri As String        ' nome da tag que será assinada (Ex. infNFe)
Dim nomeCertificado As String   ' nome (assunto) do certificado digita
Dim XMLAssinado As String   ' retorna com o xml assinado
Dim msgResultado As String  ' literal com resultado da chamada da DLL
Dim Resultado As Long       ' código do resultado da chamada da DLL
'
'
'  IMPORTANTE: todas as variáveis utilizadas como parâmetro da DLL devem ser inicializadas
'
'
Dim nomeArquivo As String   ' nome do arquivo que será assinado
'
nomeArquivo = "c:\exemplo.xml"
'
' importante: verificar a existência do arquivo solicitado na pasta do VB e indicar o caminho correto para ele
'   Carrega o conteúdo do nome do arquivo em XMLString
'
Open nomeArquivo For Input As #1
XMLString = Input$(LOF(1), 1)
Close #1
'
RefUri = "infNFe"           ' indica a tag a ser assinada
msgResultado = ""
nomeCertificado = "CN=NFe - Associacao NF-e:99999090910270, C=BR, L=PORTO ALEGRE, O=Teste Projeto NFe RS, OU=Teste Projeto NFe RS, S=RS"
'
' importante: indicar aqui assunto do certificado digital válido, este da associacao trata-se apenas de um exemplo para testes
'
' EXEMPLO PARA USO DE ARQUIVO PFX
'
'nomeCertificado = "ARQUIVO|c:\certificado.pfx|associacao"
'
'  onde:
'  ARQUIVO            --> indica opção de uso de arquivo PFX
'  c:\certificado.pfx --> nome e caminho do arquivo PFX
'  associacao         --> senha do arquivo PFX
'
'
' EXEMPLO PARA USO DE ARQUIVO PFX EM STRING BASE64
'
'nomeCertificado = "CERTIFICADO|MIIGoDCCBYigAwIBAgIQep(arquivo pfx do certificado digital convertido em base64...)QQDExNBQy|senha"
'
'  onde:
'  CERTIFICADO        --> indica opção de uso de arquivo PFX em base64
'  MIIGoDCCBYigAwIBAgIQep(arquivo pfx do certificado digital convertido em base64...)QQDExNBQy --> arquivo PFX em base64
'  senha              --> senha do arquivo PFX
'
'  utilize a funcioalidade string ConverteArquivoBase64(string nomeArquivo, out int cResultado, out string msgResultado) para criar a string base64 do arquivo pfx
'
Dim objNFeUtil As Object
'
' instancia a DLL
'
Set objNFeUtil = CreateObject("NFe_Util_2G.util")
'
Resultado = 0
'
' Aplica a assinatura
'
XMLAssinado = objNFeUtil.Assinar(XMLString, RefUri, nomeCertificado, Resultado, msgResultado)
'
'  tratar retorno
'
If Resultado = 5300 Then
 
MsgBox msgResultado, vbInformation, "Informação"
 
Else
 
MsgBox "Processo de assinatura falhou..." & vbCrLf & msgResultado, vbExclamation, "Atenção"
 
End If
'
'  liberar DLL
'
Set objNFeUtil = Nothing
13.1.1. Assinar
13.1. Assinatura XML
« Anterior
13.1. Assinatura XML
Próximo »
13.1.2. Assinar NFC-e