Ir para conteúdo
  • Cadastre-se

dev botao

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


  • Este tópico foi criado há 2233 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

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.

  • Curtir 1
Link para o comentário
Compartilhar em outros 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.

  • Curtir 1
Link para o comentário
Compartilhar em outros 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....

Link para o comentário
Compartilhar em outros 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;

 

Link para o comentário
Compartilhar em outros 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

Link para o comentário
Compartilhar em outros 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....

Link para o comentário
Compartilhar em outros 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);

Link para o comentário
Compartilhar em outros 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

Link para o comentário
Compartilhar em outros 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.

Link para o comentário
Compartilhar em outros 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.

Link para o comentário
Compartilhar em outros 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?

 

Link para o comentário
Compartilhar em outros 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. 

Link para o comentário
Compartilhar em outros 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

Link para o comentário
Compartilhar em outros 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...

Editado por tiago.prs
Link para o comentário
Compartilhar em outros 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

Editado por juuninho
Link para o comentário
Compartilhar em outros sites

  • Este tópico foi criado há 2233 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.
Visitante
Este tópico está agora fechado para novas respostas
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.

The popup will be closed in 10 segundos...