- 11.1. Assinatura XML
11.1.1. Assinar - 11.1. Assinatura XML
« Anterior - 11.2. Certificado Digital
Próximo »
11.1.1. Assinar
Assinatura Digital XML no padrão do Projeto CT-e
Assinatura
int Assinar(string XMLString, string RefUri, string Nome, out string XMLAssinado, 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.
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. infCte) com a referência da URI a ser assinada. |
| Nome | string | entrada | informar o assunto do certificado que será utilizado para assinar o XML |
| XMLAssinado | string | saída | retorna string XML assinada |
| msgResultado | string | saída | 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 criptografia assimétrica no resumo da mensagem (message digest) com a chave privada do assinante. Qualquer alteração do conteúdo do XML do CT-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 do CT-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 assinatua 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 do CT-e tenta importar o arquivo XML do CT-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 e º tem representação diferente no ANSI e no UTF-8, o grande problema é que o UTF-8 é multibyte e alguns caracteres são representados com 2 bytes e neste processo pode ocorrer o sumiço de algum byte com reflexo na assinatura digital. 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, com as devidas adequações ao projeto CT-e.
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 CT-e em uma estrutura de lote
A DLL não permite a assinatura de um CT-e contido em uma estrutura de lote de CT-e, assim, a assinatura do CT-e deve ser realizada individualmente.
O uso de namespaces
A tag raiz do XML deve ter o namespace do projeto (xmlns="http://www.cte.fazenda.gov.br/") 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.
O resultado da assinatura é o código numérico devolvido no parâmetro msgResultado com os seguintes significados:
| código | Mensagem |
|---|---|
| 0 | Assinatura realizada com sucesso |
| 1 | Erro: Problema ao acessar o certificado digital - exceção |
| 2 | Certificado digital inexistente para nome |
| 3 | XML mal formado + exceção |
| 4 | A tag de assinatura RefUri inexiste |
| 5 | A tag de assinatura RefUri não é unica |
| 6 | Erro Ao assinar o documento - ID deve ser string [RefUri(Atributo)] |
| 7 | Erro: Ao assinar o documento - exceção |
Histórico de atualização:
- Versão inicial.
- 2011-12-16 - Acréscimo do código exemplo em VB 6.0.
Exemplos de uso:
Visual Basic 6.0
' ' declaração das variáveis que serão utilizadas na passagem de parâmetros da DLL ' Dim XMLString As String ' informar uma string com o XML que será assinado. Dim RefUri As String ' indica a tag a ser assinada (Ex. infCTe) Dim Nome As String ' informar o Nome do titular (campo Assunto) do certificado digital a ser utilizado na conexão SSL. Ex.: "CN=NFe - Associacao NF-e:99999090910270, C=BR, L=PORTO ALEGRE, O=Teste Projeto NFe RS, OU=Teste Projeto NFe RS, S=RS" Dim XMLAssinado As String ' retorna o XML assinado Dim msgResultado As String ' retorna a literal com resultado da chamada da DLL Dim resultado As Long ' retorna 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 = "infCte" ' indica a tag a ser assinada msgResultado = "" Nome = "CN=NFe - Associacao NF-e:99999090910270, C=BR, L=PORTO ALEGRE, O=Teste Projeto NFe RS, OU=Teste Projeto NFe RS, S=RS" resultado = 0 ' retorna código do resultado da chamada da DLL ' ' referenciando a DLL em late binding ' não é necessário fazer o reference da DLL ' o intelisense não funciona ' Dim objCTeUtil As Object Set objCTeUtil = CreateObject("CTe_Util.Util") Screen.MousePointer = vbHourglass ' ponteiro ampulheta ' ' houve alteração nos parâmetros de retorno, agora o XMLAssinado é devolvido pela funcionalidade ' resultado = objCTeUtil.Assinar(XMLString, RefUri, Nome, XMLAssinado, msgResultado) ' ' Screen.MousePointer = vbDefault ' ponteiro normal ' ' tratar retorno ' If resultado = 0 Then ' ' grava CT-e Assinado ' nomeArquivo = "XMLAssinado.xml" Open nomeArquivo For Output As #1 Print #1, XMLAssinado Close #1 MsgBox msgResultado + Chr(13) + Chr(13) + XMLAssinado, vbInformation, "Informação" ' ' Else MsgBox "Processo de assinatura falhou..." & vbCrLf & msgResultado, vbExclamation, "Atenção" End If ' ' liberar DLL ' Set objCTeUtil = Nothing
- 11.1.1. Assinar
11.1. Assinatura XML - « Anterior
11.1. Assinatura XML - Próximo »
11.2. Certificado Digital