Você está na página 1de 4

Assinatura Digital em Arquivos XML

Jul 11, 2016


3 minute read

A Assinatura Digital cada vez mais utilizada devido a segurana de integridade que ela proporciona. Nesse artigo vou demostrar como
Assinar Digitalmente um arquivo XML utilizando o framework ACBr.

Introduo
A Assinatura Digital nos d mais segurana no envio de arquivos entre servidores, utilizando WebServices e/ou Servios REST.
No mundo Java e .NET tem-se muitos frameworks para trabalhar com Assinatura Digital mas e em Object Pascal?
Eu conhecia o Projeto ACBr a muito tempo. Eu utilizei esse projeto, anos atrs, para fazer a integrao de NF-e para um cliente que, na
poca, utilizava Delphi 6.
A integrao foi feita em apenas 1 semana conte com as madrugadas e tudo funcionou perfeitamente.
Anos se passaram e eu no tive mais projetos que envolvessem NF-e e/ou Assinatura Digital. Pelo menos no que eu mesmo tivesse que
implement-los.

Este ano eu tenho um Novo Projeto.


Nesse projeto tenho que utilizar Assinatura Digital em arquivos XML. No so Notas Fiscais Eletrnicas (NF-e). So arquivos XML que
precisam ser assinados antes do envio e verificados na outra ponta. A segurana levado muito a srio nesse projeto.
Lembrei do Projeto ACBr, claro.

Utilizando o ACBr
O ACBr trabalha com dois tipos de Assinadores: CAPICOM (Microsoft) e OpenSSL (OpenSource e crossplataforma).
Meu cliente s utiliza Windows, ento eu escolhi a opo mais bvia.
O ACBr compila em Delphi e FreePascal perfeitamente.
Para instalar no Delphi mais fcil. O projeto dispe de um Instalador next-next-finish.
Para instalar no FreePascal eu no sei se o mesmo instalador. O que fiz foi instalar os pacotes manualmente, pela IDE do Lazarus.
Ento fiz um programa simples para assinar um XML e tentar validar o resultado em um dos WebServices do cliente.
Precisei criar o XML Template, que o XML que tenho que enviar ao WebService:
<?xml version="1.0" encoding="iso-8859-1"?>
<Principal>
<Solicitacao Id="123"><Parametros Codigo="Todos" /></Solicitacao>
<Assinatura>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#123">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue/>
</Signature>
</Assinatura>
</Principal>

Veja que j existe os ns da assinatura (Signature), mas esto em branco ou incompletos. Esse o template que o ACBr ir utilizar para
realmente assinar e gerar um novo XML.
Ento codifiquei um pequeno programa em Object Pascal para fazer os testes.
procedure TMainForm.Assinar;
var
A: TDFeSSL;
I: Integer;
begin
A := TDFeSSL.Create;
A.SSLLib := libCapicom;
A.SelecionarCertificado;
with TStringList.Create do
try
// carrega o XML de template
LoadFromFile('template.xml');

// obtm o XML assinado no Text do StringList


Text := '<?xml version="1.0" encoding="iso-8859-1"?>'
+ A.Assinar(Text, 'Assinatura', '');
// salva o XML em disco
SaveToFile('assinado.xml');
finally
Free;
end;
A.Free;
end;

A tela para escolher o certificado previamente instalado no computador aparece e o usurio, que pode selecionar qual ele deseja.
O XML assinado (node Assinatura) e tudo parece perfeito mas o WebService do cliente no valida a Assinatura.
Algo estava errado.

Soluo
Aps ajuda do pessoal do ACBr e amigos, chegamos a concluso que os espaos em branco no Template eram o problema.
Modifiquei o projeto de teste, intruduzindo algumas linhas de cdigo para retirar os espaos e quebras de linha. Funcionou.
procedure TMainForm.Assinar;
var
A: TDFeSSL;
S: AnsiString;
I: Integer;
begin
A := TDFeSSL.Create;
A.SSLLib := libCapicom;
A.SelecionarCertificado;
with TStringList.Create do
try
// carrega o XML de template
LoadFromFile('template.xml');
S := '';
// retira dos os espaos em braco e quebras de linha
for I := 0 to Count-1 do
begin
S := S + Trim(
StringReplace(
StringReplace(Strings[I], #13, '', [rfReplaceAll]),
#10, '', [rfReplaceAll]
)
)
end;
// obtm o XML assinado no Text do StringList
Text := '<?xml version="1.0" encoding="iso-8859-1"?>'
+ A.Assinar(S, 'Assinatura', '');
// salva o XML em disco
SaveToFile('assinado.xml');
finally
Free;
end;
A.Free;
end;

Concluso
O Projeto ACBr me ajudou bastante me poupando muito tempo de desenvolvimento.

H alguns detalhes que no mencionei. Foram necessrios pequenas modificaes no cdigo do ACBr devido a alguns nodes customizados
que eu precisa fazer no XML mas que o ACBr original no suportava. Essas modificaes foram enviadas aos programadores do ACBr.
isso.
Agradeo a todos os desenvolvedores e amigos que ajudaram na soluo.
Obrigado e at logo.