Ir para conteúdo
  • Cadastre-se

dev botao

Método VerificarAssinatura com CAPICOM


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

Recommended Posts

Daniel,

Pensando melhor agora, eu não poderia usar a função PKCS12parse, visto que um dos parâmetros é a senha e... eu não as tenho.

Cada arquivo enviado ao servidor será assinado por um certificado diferente, de pessoas diferentes. Por isso preciso identificar o CPF pra saber quem assinou.

Bem, pelo que entendi no link que vc passou, um nó X509 estaria num formato P7B/PKCS#7:

P7B/PKCS#7
They contain “—–BEGIN PKCS—–” & “—–END PKCS7—–” statements. It can contain only Certificates & Chain certificates but not the Private key.
> They are Base64 encoded ASCII files
> They have extensions .p7b, .p7c
> Several platforms supports it. eg:- Windows OS, Java Tomcat

Então tentei utilizar os códigos abaixo:

Convert P7B to PFX
——————————————————————————————————————————————————-
$ openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
$ openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CAcert.cer

Mas sem sucesso.

Também adicionei no arquivo (que contém os dados em base64) os statements “—–BEGIN PKCS—–” & “—–END PKCS7—–” mas também sem sucesso.

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Não.. no XML, a tag X509, usa o formato "DER", em Base64

Tente esse site: https://www.sslshopper.com/ssl-converter.html

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Mas, Daniel, eu mesmo falei sobre esse site aqui...

De qq forma, vc consegue utilizar o exe do openssl e fazer as conversões na linha de comando? Porque aqui eu não consigo. Sempre dá erro.

O certificado que eu utilizo é um de teste (disponibilizado pelo meu cliente) sem senha. Não sei se isso impacta em alguma coisa, apenas mais uma informação.

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Sim, já usei o OpenSSL por linha de comando, no Windows e Linux...

Nunca tentei capturar as informações do X509 contido na assinatura do XML... precisaria gastar algumas horas para tentar isso... farei assim que tiver um tempo disponível...

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Por favor teste com as Units em Anexo...

Modo de uso...

procedure TForm1.Button9Click(Sender: TObject);
begin
  with TDFeOpenSSL(ACBrNFe1.SSL.SSLClass) do
  begin
     LerX509Info( ConteudoTag_X509Certificate );
  end;
end;   

 

ACBrDFeOpenSSL.pas

OpenSSLExt.pas

  • Curtir 1
Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Estou obtendo alguns erros:

Compile package ACBrDFeComum 0.0: Exit code 1, Errors: 2
ACBrDFeOpenSSL.pas(125,14) Error: There is no method in an ancestor class to be overridden: "GetCertIssuerName:AnsiString;"
ACBrDFeOpenSSL.pas(126,14) Error: There is no method in an ancestor class to be overridden: "GetCertCertificadora:AnsiString;"

Então retirei os "overrides".

Compilando novamente... erro:

ACBrDFeOpenSSL.pas(988,21) Error: Identifier not found "GetCertificadoraFromSubjectName"

Acho que vc conseguiu compilar porque deve ter usando a versão já compilada memória, talvez... então basta dar um Build All pra ver esses erros aí também.

 

EDIT:
OK, acho que entendi. Preciso atualizar os fontes do SVN.

Editado por mdbs99

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

Daniel, 

Tá quase!

Eu tentei dessa forma abaixo.
Onde o atributo "FX509Certificate" é o conteúdo do Node que vem no XML.

function TSignatureCPFInfo.Value: string;
var
  A: TDFeSSL;
begin
  A := TDFeSSL.Create;
  try
    A.SSLLib := libOpenSSL;
    with TDFeOpenSSL(A.SSLClass) do
    begin
      LerX509Info(FX509Certificate);
      Result := CertSubjectName;
    end;
  finally
    A.Free;
  end;
end;

O resultado, no entanto, vem assim:


C=BR, O=ICP-Brasil, OU=Secretaria da Receita Federal do Brasil - RFB, OU=RFB e-CPF A3, OU=Certificado de Teste, OU=Autenticado por Irreal Certificadora Digital Virtual, CN=\x00A\x00N\x00D\x00R\x00\xC9\x00 \x00D\x00O\x00 \x00E\x00S\x00P\x00\xCD\x00R\x00I\x00T\x00O\x00 \x00S\x00A\x00N\x00T\x00O\x00 \x00B\x00O\x00G\x00A\x00D\x00O\x00:\x000\x004\x007\x00.\x008\x008\x001\x00.\x009\x000\x007\x00-\x002\x009

 

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Marcos,

Achei algo que parece ser o nosso caso...

O Nome e CPF estão em UTF16

http://security.stackexchange.com/questions/31760/what-are-those-nul-bytes-doing-in-certificate-subject-cn

Poderíamos fazer uma rotina que converta ele de UTF16 para UTF8

Tentei algo, como abaixo... mas sem sucesso.

var
  UTF16Str: WideString;
bagin
  // Verifica se está codificado em UTF16
  if (pos('\x00', Result) > 0) then
  begin
    UTF16Str := StringToBinaryString(Result);
    Result := UTF8Encode(UTF16Str);
  end;
       

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Consultores
28 minutos atrás, Daniel Simoes disse:

Marcos,

Achei algo que parece ser o nosso caso...

O Nome e CPF estão em UTF16

http://security.stackexchange.com/questions/31760/what-are-those-nul-bytes-doing-in-certificate-subject-cn

 

Daniel,

   no comentário da resposta, o rapaz diz que se usar o comando "openssl x509 -nameopt sep_comma_plus_space" o openssl consegue ler o certificado corretamente.

   Será que não seria o caso de tentar descobrir como conseguir a mesma funcionalidade de passar esse parâmetro ao ler o certificado?

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

6 horas atrás, Daniel Simoes disse:

Achei algo que parece ser o nosso caso...

O Nome e CPF estão em UTF16

http://security.stackexchange.com/questions/31760/what-are-those-nul-bytes-doing-in-certificate-subject-cn

Realmente parece que todo o resto é lido corretamente mas especificamente o Nome/RazãoSocial parece estar codificado diferente.

Pode ser isso, codificado em UTF-16.

Vou ver se consigo fazer alguma coisa no FreePascal.

5 horas atrás, EMBarbosa disse:

Será que não seria o caso de tentar descobrir como conseguir a mesma funcionalidade de passar esse parâmetro ao ler o certificado?

É uma boa ideia. Se já existir essa opção nas funções da DLL pode ser algo mais prático a se fazer (talvez pra vocês que já conhecem a estrutura).

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Esse parâmetro somente estaria disponível no método " X509_NAME_print_ex()", nos fontes da biblioteca em pascal, somente temos: "X509_NAME_oneline"

https://www.openssl.org/docs/manmaster/crypto/X509_NAME_print_ex.html

 

Acho mais simples descobrir uma maneira de converter UTF16 para UTF8

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

31 minutos atrás, Daniel Simoes disse:

Acho mais simples descobrir uma maneira de converter UTF16 para UTF8

Pode ser.

Uma dúvida: Essa codificação não deveria ser padrão em todos os certificados?

Outra: Mesmo que consigamos converter, como iremos saber se devemos ou não converter? Fico pensando se há algum "flag" em algum lugar informando o "padrão" ou o "encode" que foi utilizado.

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

  • Consultores
8 minutos atrás, mdbs99 disse:

Pode ser.

Uma dúvida: Essa codificação não deveria ser padrão em todos os certificados?

Parece que não.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

  • Fundadores

Realmente não tem um "BOM", como deveria ser... para definir o Encoding...

O que poderiamos fazer, é verificar a presença do NUL (0)... se ele existir, provavelmente está sendo utilizado UTF16... Para piorar, a codificação em UTF16 pode ser em Little Endian (NUL na frente) ou Big Endian (NUL atrás)

https://pt.wikipedia.org/wiki/UTF-16

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Seguindo a ideia que peguei lá na lista FPC, tentei utilizar as funções da unit LConvEncoding... porém sem sucesso.

Outra ideia, também lá da lista, é utilizar esse projeto http://chsdet.sourceforge.net


Mas agora me ocorreu uma ideia: Os componentes do ACBr estão preparados para ler Certificados de CNPJ, tanto que os nomes dos métodos tem relação com PJ. Mas, se estou utilizando Certificado de PF, é possível que o ACBr — especificamente o TDFeOpenSSL — está lendo as informações em "posições" erradas? Eu ainda não sei, vou pesquisar, mas creio que o Certificado de PJ pode ser diferente do PF.

O que acham?

Marcos Douglas B. Santos
www.ObjectPascalProgramming.com

Link para o comentário
Compartilhar em outros sites

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

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • 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.