Jump to content

Promoção 25 Anos de Delphi
25% de desconto em todas as versões

Saiba mais

Ganhe o curso Tributação NF-e para Desenvolvedores

Assinando o SAC Anual este mês
botao.png

 

Balança SM100 performance surpreendente

Tecnologia Japonesa   Teclado e Visor resistentes a água
Consumo inteligente de etiquetas   Baixo custo de manutenção
Comunicação Ethernet e WIFI independentes

Saiba Mais

Impressora de Etiquetas ELGIN - L42 PRO

Protocolos PPLA, PPLB, ZPL, EPL (automático)
Porta USB padrão Opcionais: Ethernet, Serial, Paralela
Sensor de Etiquetas Móvel Garantia de 18 meses

Saiba mais

Leivio Fontenele

Uma Opção Certificação A3/SHA256 - Fontes

Recommended Posts

[Solved] Assinatura A3 com SHA256.

 

Uma opção que achei junto ao um amigo meu que é programador C# foi criar uma DLL em C# para fazer a assinatura. Basicamente, a gente manda o XML e a DLL devolve assinada, apenas isso. A DLL foi feita baseada no CertFly e é consumida pelo o método 'Assinar' da classe 'TDFeSSLXmlSignClass' que fica localizada no arquivo 'ACBrDFeSSL'.

[Código aberto]

https://github.com/tiagopsilva/eSocialSignature

 

[Como usar]

No arquivo 'ACBrDFeSSL' coloque 'eSocialSignature' no 'uses' da 'interface'. Depois disso apague tudo que está no método 'Assinar' e substitua por esse código:

var
  xml: PAnsiChar;
begin
   FpDFeSSL.SetSSLXmlSignLib(xsXmlSec);
   FpDFeSSL.SSLCryptLib := cryCapicom;

   xml := PAnsiChar(AnsiString(ConteudoXML));
   TESocialSignature.SignSHA256Ansi(xml, PAnsiChar(AnsiString(infElement)),
                                         PAnsiChar(AnsiString(FpDFeSSL.NumeroSerie)),
                                         PAnsiChar(AnsiString(FpDFeSSL.Senha)));
   Result := string(AnsiString(xml));

 

Isso é a única coisa que precisa ser alterada no plugin da ACBReSocial. Porém, é necessário definir a 'SSLLib' para 'libCustom' nas configurações do 'ACBreSocial', exemplo:

If ( Obj.Modelo = A3 ) Then
         Begin
            If Not FConsultar Then
               AACBreSocial.Configuracoes.Geral.SSLLib := libCustom
            Else
               AACBreSocial.Configuracoes.Geral.SSLLib := libCapicom;

            AACBreSocial.Configuracoes.Certificados.NumeroSerie := Obj.NumeroSerie;
            AACBreSocial.SSL.CarregarCertificado;
         End;

 

Para facilitar, apenas uso a 'libCustom' na hora de exportar já que o problema estava na assinatura do XML. Quando eu consulto eu já deixo o plugin fazer o processo dele normalmente, já que, na consulta não é necessário a assinatura digital. Porém, no código da ACBR pede o carregamento do certificado, e eu estava com problemas no método 'EnviarDados' da classe 'TDFeWebService' que fica no arquivo 'ACBrDFeWebService'. Quando o método executa '(FPDFeOwner.SSL.CertDataVenc < Now)' da problemas, pois, o 'CertDataVenc' vem com o valor default e não do certificado. Então preferi fazer essa estratégia com a flag do que sobrescrever mais o código original.

  • Like 1

Share this post


Link to post
Share on other sites
23 horas atrás, Jeihcio Francis disse:

[Solved] Assinatura A3 com SHA256.

 

Uma opção que achei junto ao um amigo meu que é programador C# foi criar uma DLL em C# para fazer a assinatura. Basicamente, a gente manda o XML e a DLL devolve assinada, apenas isso. A DLL foi feita baseada no CertFly e é consumida pelo o método 'Assinar' da classe 'TDFeSSLXmlSignClass' que fica localizada no arquivo 'ACBrDFeSSL'.

[Código aberto]

https://github.com/tiagopsilva/eSocialSignature

 

[Como usar]

No arquivo 'ACBrDFeSSL' coloque 'eSocialSignature' no 'uses' da 'interface'. Depois disso apague tudo que está no método 'Assinar' e substitua por esse código:

var
  xml: PAnsiChar;
begin
   FpDFeSSL.SetSSLXmlSignLib(xsXmlSec);
   FpDFeSSL.SSLCryptLib := cryCapicom;

   xml := PAnsiChar(AnsiString(ConteudoXML));
   TESocialSignature.SignSHA256Ansi(xml, PAnsiChar(AnsiString(infElement)),
                                         PAnsiChar(AnsiString(FpDFeSSL.NumeroSerie)),
                                         PAnsiChar(AnsiString(FpDFeSSL.Senha)));
   Result := string(AnsiString(xml));

 

Isso é a única coisa que precisa ser alterada no plugin da ACBReSocial. Porém, é necessário definir a 'SSLLib' para 'libCustom' nas configurações do 'ACBreSocial', exemplo:

If ( Obj.Modelo = A3 ) Then
         Begin
            If Not FConsultar Then
               AACBreSocial.Configuracoes.Geral.SSLLib := libCustom
            Else
               AACBreSocial.Configuracoes.Geral.SSLLib := libCapicom;

            AACBreSocial.Configuracoes.Certificados.NumeroSerie := Obj.NumeroSerie;
            AACBreSocial.SSL.CarregarCertificado;
         End;

 

Para facilitar, apenas uso a 'libCustom' na hora de exportar já que o problema estava na assinatura do XML. Quando eu consulto eu já deixo o plugin fazer o processo dele normalmente, já que, na consulta não é necessário a assinatura digital. Porém, no código da ACBR pede o carregamento do certificado, e eu estava com problemas no método 'EnviarDados' da classe 'TDFeWebService' que fica no arquivo 'ACBrDFeWebService'. Quando o método executa '(FPDFeOwner.SSL.CertDataVenc < Now)' da problemas, pois, o 'CertDataVenc' vem com o valor default e não do certificado. Então preferi fazer essa estratégia com a flag do que sobrescrever mais o código original.

funcionou 100%.

Parabéns.

  • Like 1

Share this post


Link to post
Share on other sites
2 horas atrás, LUIZTEC disse:

Substitui o arquivo ACBrDFeSSL.pas e quando vai assinar mostra o erro "External exception E0434352", linha do Esocialsignature.dll ->   proc(AXml, ANodeToSign, ASerialNumber, APassword);

Share this post


Link to post
Share on other sites

Acabei de testar e eu mesmo tive problemas, quando eu tento exportar um lote com mais de um evento está dando a seguinte mensagem de erro: "Certificado não permite Exportar Chave Privada.". Ele acontece no arquivo 'ACBrDFeWinCrypt' no método "ExportCertContextToPFXData" na linha 681, onde tem:

if not PFXExportCertStoreEx( AStore, PFXBlob,
                                 LPCWSTR(WideString( APass )),
                                 Nil, dwFlags) then
      raise EACBrDFeExceptionNoPrivateKey.Create('Certificado não permite Exportar Chave Privada.');

 

Alguém sabe o motivo? Estranho, por que certificado A3 não tem PFX, então não era para está chamando todo esse processo....

Share this post


Link to post
Share on other sites
17 horas atrás, Jeihcio Francis disse:

Acabei de testar e eu mesmo tive problemas, quando eu tento exportar um lote com mais de um evento está dando a seguinte mensagem de erro: "Certificado não permite Exportar Chave Privada.". Ele acontece no arquivo 'ACBrDFeWinCrypt' no método "ExportCertContextToPFXData" na linha 681, onde tem:

if not PFXExportCertStoreEx( AStore, PFXBlob,
                                 LPCWSTR(WideString( APass )),
                                 Nil, dwFlags) then
      raise EACBrDFeExceptionNoPrivateKey.Create('Certificado não permite Exportar Chave Privada.');

 

Alguém sabe o motivo? Estranho, por que certificado A3 não tem PFX, então não era para está chamando todo esse processo....

Minhas configurações estão assim e está funcionando normalmente, até para vários eventos: (nao usei libcustom)

  VESocial.Configuracoes.Geral.SSLLib        := libOpenSSL;  
  VESocial.Configuracoes.Geral.SSLHttpLib    := httpWinHttp; 
  VESocial.Configuracoes.Geral.SSLCryptLib   := cryWinCrypt; 
  VESocial.Configuracoes.Geral.SSLXmlSignLib := xsXmlSec;   

  VESocial.SSL.SelecionarCertificado;

 

Share this post


Link to post
Share on other sites
1 hora atrás, LUIZTEC disse:

Minhas configurações estão assim e está funcionando normalmente, até para vários eventos: (nao usei libcustom)

  VESocial.Configuracoes.Geral.SSLLib        := libOpenSSL;  
  VESocial.Configuracoes.Geral.SSLHttpLib    := httpWinHttp; 
  VESocial.Configuracoes.Geral.SSLCryptLib   := cryWinCrypt; 
  VESocial.Configuracoes.Geral.SSLXmlSignLib := xsXmlSec;   

  VESocial.SSL.SelecionarCertificado;

 

Utilizando o seu ACBrDFeSSL.pas dá erro ao compilar o ACBr_DFeComum, segue o erro abaixo:

    function ValidarHash( const AStream : TStream;
       const Digest: TSSLDgst;
       const Hash: AnsiString;
       const Assinado: Boolean =  False): Boolean; override;
 

Erro no ACBrDFeWinCrypt.pas

Share this post


Link to post
Share on other sites

Eu acabei resolvendo o problema que mencionei acima da seguinte forma: 

 

Configurações do componente:

 

If ( Obj.Modelo = A3 ) Then
         Begin
            If FConsultar Then
               AACBreSocial.Configuracoes.Geral.SSLLib := libCapicom
            Else
               AACBreSocial.Configuracoes.Geral.SSLLib := libCustom;

            AACBreSocial.Configuracoes.Geral.SSLXmlSignLib := xsNone;
            AACBreSocial.Configuracoes.Certificados.NumeroSerie := Obj.NumeroSerie;
            AACBreSocial.SSL.CarregarCertificado;
         End;

 

Obs: Eu sei que por default o 'SSLXmlSignLib' vem 'xsNone', mas eu quis deixar explicitamente no código do meu controller que é obrigatório setar esse valor no atributo. 

 

Depois e antes de enviar eu faço:

 

{ Assinatura digital }
ACBreSocial1.AssinarEventos;

{ Enviar dados ao webservice }
ACBreSocial1.Configuracoes.Geral.SSLXmlSignLib := xsXmlSec;
ACBreSocial1.Enviar(getTipoGrupo(nTabela));

 

Antes de enviar é obrigatório setar 'xsXmlSec'  para a propriedade 'SSLXmlSignLib', pois no método 'Enviar' da classe 'TACBreSocial' que fica dentro do arquivo 'ACBReSocial' existe a seguinte verificação: 

 

if SSL.SSLXmlSignLib <> xsXmlSec then
    raise EACBreSocialException.Create('Necessário DigestMethod Algorithm = sha256 -> SSLLib = libOpenSSL'); 

 

Essas configurações eu fiz no meu código da minha aplicação, já no componente da ACBR tive que fazer as seguintes alterações no arquivo 'ACBrDFeSSL':

 

Método 'Assinar' da classe 'TDFeSSLXmlSignClass':

 

function TDFeSSLXmlSignClass.Assinar(const ConteudoXML, docElement,
  infElement: String; SignatureNode: String; SelectionNamespaces: String;
  IdSignature: String; IdAttr: String): String;
var
  xml: PAnsiChar;
begin
   FpDFeSSL.SSLCryptLib := cryCapicom;

   xml := PAnsiChar(AnsiString(ConteudoXML));
   TESocialSignature.SignSHA256Ansi(xml, PAnsiChar(AnsiString(infElement)),
                                         PAnsiChar(AnsiString(FpDFeSSL.NumeroSerie)),
                                         PAnsiChar(AnsiString(FpDFeSSL.Senha)));
   Result := string(AnsiString(xml));
end;

 

e no método 'Validar' dessa mesma classe:

 

function TDFeSSLXmlSignClass.Validar(const ConteudoXML, ArqSchema: String; out
  MsgErro: String): Boolean;
var
  DFeSSL: TDFeSSL;
begin
   DFeSSL := TDFeSSL.Create;
   Try
      DFeSSL.SetSSLXmlSignLib(xsXmlSec);
      Result := DFeSSL.Validar(ConteudoXML, ArqSchema, MsgErro);
   Finally
      DFeSSL.Free;
   End;
end;

 

Essas foram as unicas alterações que fiz para resolver o problema....

Share this post


Link to post
Share on other sites
39 minutos atrás, Jeihcio Francis disse:

Eu acabei resolvendo o problema que mencionei acima da seguinte forma: 

 

Configurações do componente:

 

If ( Obj.Modelo = A3 ) Then
         Begin
            If FConsultar Then
               AACBreSocial.Configuracoes.Geral.SSLLib := libCapicom
            Else
               AACBreSocial.Configuracoes.Geral.SSLLib := libCustom;

            AACBreSocial.Configuracoes.Geral.SSLXmlSignLib := xsNone;
            AACBreSocial.Configuracoes.Certificados.NumeroSerie := Obj.NumeroSerie;
            AACBreSocial.SSL.CarregarCertificado;
         End;

 

Obs: Eu sei que por default o 'SSLXmlSignLib' vem 'xsNone', mas eu quis deixar explicitamente no código do meu controller que é obrigatório setar esse valor no atributo. 

 

Depois e antes de enviar eu faço:

 

{ Assinatura digital }
ACBreSocial1.AssinarEventos;

{ Enviar dados ao webservice }
ACBreSocial1.Configuracoes.Geral.SSLXmlSignLib := xsXmlSec;
ACBreSocial1.Enviar(getTipoGrupo(nTabela));

 

Antes de enviar é obrigatório setar 'xsXmlSec'  para a propriedade 'SSLXmlSignLib', pois no método 'Enviar' da classe 'TACBreSocial' que fica dentro do arquivo 'ACBReSocial' existe a seguinte verificação: 

 

if SSL.SSLXmlSignLib <> xsXmlSec then
    raise EACBreSocialException.Create('Necessário DigestMethod Algorithm = sha256 -> SSLLib = libOpenSSL'); 

 

Essas configurações eu fiz no meu código da minha aplicação, já no componente da ACBR tive que fazer as seguintes alterações no arquivo 'ACBrDFeSSL':

 

Método 'Assinar' da classe 'TDFeSSLXmlSignClass':

 

function TDFeSSLXmlSignClass.Assinar(const ConteudoXML, docElement,
  infElement: String; SignatureNode: String; SelectionNamespaces: String;
  IdSignature: String; IdAttr: String): String;
var
  xml: PAnsiChar;
begin
   FpDFeSSL.SSLCryptLib := cryCapicom;

   xml := PAnsiChar(AnsiString(ConteudoXML));
   TESocialSignature.SignSHA256Ansi(xml, PAnsiChar(AnsiString(infElement)),
                                         PAnsiChar(AnsiString(FpDFeSSL.NumeroSerie)),
                                         PAnsiChar(AnsiString(FpDFeSSL.Senha)));
   Result := string(AnsiString(xml));
end;

 

e no método 'Validar' dessa mesma classe:

 

function TDFeSSLXmlSignClass.Validar(const ConteudoXML, ArqSchema: String; out
  MsgErro: String): Boolean;
var
  DFeSSL: TDFeSSL;
begin
   DFeSSL := TDFeSSL.Create;
   Try
      DFeSSL.SetSSLXmlSignLib(xsXmlSec);
      Result := DFeSSL.Validar(ConteudoXML, ArqSchema, MsgErro);
   Finally
      DFeSSL.Free;
   End;
end;

 

Essas foram as unicas alterações que fiz para resolver o problema....

Eu fiz todas essas alterações e voltou a dar o mesmo erro:

erro "External exception E0434352", linha do Esocialsignature.dll ->   proc(AXml, ANodeToSign, ASerialNumber, APassword);

Share this post


Link to post
Share on other sites
50 minutes ago, fabibona said:

Eu fiz todas essas alterações e voltou a dar o mesmo erro:

erro "External exception E0434352", linha do Esocialsignature.dll ->   proc(AXml, ANodeToSign, ASerialNumber, APassword);

Então, verifica se o A3 está conectado corretamente. Só use essa dll se for para o a3, o a1 usa o próprio ACBR

Share this post


Link to post
Share on other sites
Em 26/12/2017 at 15:27, fabibona disse:

Substitui o arquivo ACBrDFeSSL.pas e quando vai assinar mostra o erro "External exception E0434352", linha do Esocialsignature.dll ->   proc(AXml, ANodeToSign, ASerialNumber, APassword);

Há dois arquivos de DLL que precisam ser adicionados na pasta do executável do seu projeto. Está colocando as duas?
E posta o trecho do seu código que levanta a exceção ou um exemplo de como você está recebendo esse erro.

Share this post


Link to post
Share on other sites
36 minutos atrás, tiago.prs disse:

Há dois arquivos de DLL que precisam ser adicionados na pasta do executável do seu projeto. Está colocando as duas?
E posta o trecho do seu código que levanta a exceção ou um exemplo de como você está recebendo esse erro.

Realmente o problema foi esse, faltou colocar na pasta do executável o arquivo Security.Cryptography.dll , muito obrigado pela dica e agradeço também a todos e ao Jeihcio pela elaboração do projeto, agora esta funcionando perfeitamente.

Share this post


Link to post
Share on other sites

Essas soluções apresentadas ainda caem no problema que o Juliomar tinha citado em algum tópico por aí? Em relação a dependência do C# nas máquinas, não funcionamento no windows XP, etc, ou está "independente" ?

Obrigado!

Share this post


Link to post
Share on other sites
Em 05/01/2018 at 07:48, juuninho disse:

Essas soluções apresentadas ainda caem no problema que o Juliomar tinha citado em algum tópico por aí? Em relação a dependência do C# nas máquinas, não funcionamento no windows XP, etc, ou está "independente" ?

Obrigado!

A assinatura do A1 e A3 estão funcionando perfeitamente. A minha dúvida é que a assinatura do A3 é muito mais lenta que do A1. Estou assinando 80 eventos, no A1 leva segundos para fazer, já no A3 leva mais de 5 minutos.  Isso é normal, já que a assinatura do A3 é feita pelo pendrive?

 

Share this post


Link to post
Share on other sites
12 minutos atrás, LUIZTEC disse:

A assinatura do A1 e A3 estão funcionando perfeitamente. A minha dúvida é que a assinatura do A3 é muito mais lenta que do A1. Estou assinando 80 eventos, no A1 leva segundos para fazer, já no A3 leva mais de 5 minutos.  Isso é normal, já que a assinatura do A3 é feita pelo pendrive?

 

Isso mesmo @LUIZTEC... A3 é bem mais lento devido a necessidade de acesso a hardware externo para ter acesso a chave privada. o qual não ocorre com A1 haja vista que o mesmo já tem a chave privada quando exportada ao arquivo.

A3 oferece maior segurança...mais perde em performance. 

Share this post


Link to post
Share on other sites
5 horas atrás, Leivio Fontenele disse:

Isso mesmo @LUIZTEC... A3 é bem mais lento devido a necessidade de acesso a hardware externo para ter acesso a chave privada. o qual não ocorre com A1 haja vista que o mesmo já tem a chave privada quando exportada ao arquivo.

A3 oferece maior segurança...mais perde em performance. 

 

6 horas atrás, LUIZTEC disse:

A assinatura do A1 e A3 estão funcionando perfeitamente. A minha dúvida é que a assinatura do A3 é muito mais lenta que do A1. Estou assinando 80 eventos, no A1 leva segundos para fazer, já no A3 leva mais de 5 minutos.  Isso é normal, já que a assinatura do A3 é feita pelo pendrive?

 

Leivio, essa opção do CertFly também tem a dependência do C#?

Não funciona sem a versão necessária do C# instalada, e apresenta incompatibilidade com o Windows XP?

Eu fiz testes com o Polictryp que alguém disponibilizou aqui no fórum também, e funcionou perfeito com A1 e A3 também...

Mas isso só internamente aqui na empresa, ainda não disponibilizamos para nenhum cliente, estamos aguardando uma posição oficial em relação a assinatura com o A3...se vai haver solução que não dependa do C# e de S.O

Share this post


Link to post
Share on other sites

Se ao dizerem que depende do C# é depender do .NET Framework instalado, então sim!
Precisa da versão 4.0 instalada, que é a última compatível com o Windows XP e que vêm já no Service Pack 3.
O Windows Seven, se não me engano vêm com o .NET 3.5, o que fará depender da instalação do 4.0.

Isso com a eSocialSignature.dll, juntamente da Security.Cryptografy.dll.

Já a CertFly pelo o vi esta usando o .NET 4.6.1.

Mas o pessoal da ACBr com certeza deve liberar uma solução para isso.
Com Lazarus é possível.
Aguardemos...

Edited by tiago.prs

Share this post


Link to post
Share on other sites
7 minutos atrás, tiago.prs disse:

Se ao dizerem que depende do C# é depender do .NET Framework instalado, então sim!
Precisa da versão 4.0 instalada, que é a última compatível com o Windows XP e que vêm já no Service Pack 3.
O Windows Seven, se não me engano vêm com o .NET 3.5, o que fará depender da instalação do 4.0.

Isso com a eSocialSignature.dll, juntamente da Security.Cryptografy.dll.

Já a CertFly pelo o que esta usando o .NET 4.6.1.

Mas o pessoal da ACBr com certeza deve liberar uma solução para isso.
Com Lazarus é possível.
Aguardemos...

Isso, eu estava me referindo ao .NET sim... foi mal!

Certo, então independente de S.O a dependência sera do .NET 4.0 nesse caso, certo?

Que no caso do XP, só atualizando para o SP3.

Essa eSocialSignature.dll e Security.Cryptografy.dll estão versionadas em algum lugar? (Encontrei aqui, ta com o link para o github)

Sabe me dizer se essa solução é a que será adotada nos fontes do Acbr para o e-social?

Obrigado Tiago

Edited by juuninho

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

×
×
  • Create New...