- 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.
- 2013-12-13 - Acréscimo do código exemplo em VFP.
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
Visual Foxpro
CLEAR LOCAL XMLString as String LOCAL RefUri as String LOCAL NomeCertificado as String LOCAL XMLAssinado as String LOCAL msgResultado as String LOCAL resultado as Integer LOCAL objCTeUtil as object XMLString = FILETOSTR("c:\CTeXML.xml") && inicializar todos os parâmetros RefUri = "infCte" msgResultado = "" NomeCertificado ="CN=M R M KATO ASAKURA EIRELI EPP:69621187915, OU=AC CAIXA PJ v2, OU=Caixa Economica Federal, O=ICP-Brasil, C=BR" && se NomeCertifcado = "", a DLL oferece a escolha do certificado digital resultado = 0 XMLAssinado = "" objCTeUtil = CREATEOBJECTEX("CTe_Util.util","","") resultado = objCTeUtil.Assinar(XMLString, RefUri, NomeCertificado, @XMLAssinado, @msgResultado) StrToFile(XMlAssinado,"c:\CTeXMLAssinado.xml") ? resultado ? XMLAssinado
- 11.1.1. Assinar
11.1. Assinatura XML - « Anterior
11.1. Assinatura XML - Próximo »
11.2. Certificado Digital