Assinatura Digital em qualquer rotina do sistema

01/11/2012

147

Alguém sabe de alguma função para chamar a tela do certificado digital com senha para autorizar X procedimento ? Quero autorizar o faturamento das O.S. acima de XXX valor somente após a assinatura eletrônica do gestor. Ex: Abrir a tela do certificado (aquela do windows) e se a pessoa colocou a senha correta aí sim libera a O.S. Não vou guardar a senha, só saber se ele conseguiu seguir adiante.

Outras opções de uso: Excluir a empresa matriz após assinatura digital. Liberar pagamento de boleto acima de XXX valor. E por aí vai; assinatura em rotinas complexas e/ou custosas.

Postado originalmente em [url]https://www.facebook.com/groups/DelphiBrasilforever/permalink/378546328890957[/url]
Responder

Post mais votado

01/11/2012

Você pode usar CAPICOM para fazer isso.
Tem que usar uma biblioteca que não vem com o Delphi, mais a dll da capicom, e mais o arquivo PAS gerado a partir da dll.
Estou disponibilizando os arquivos pra você.
Baixa esses arquivos:

[url]http://www.cdnweb.com.br/capicom_dll.rar[/url] Descompactar na System32 e depois executar o CapiCom.bat para registrar a dll.
[url]http://www.cdnweb.com.br/capicom_tbl.rar[/url] Descompactar na pasta Imports do Delphi.
[url]http://www.cdnweb.com.br/win32api.rar[/url] Descompactar em algum lugar e adicionar no LibraryPath do Delphi.

Feito isso colocar isso nos uses do form: CAPICOM_TLB, JwaWinCrypt, WinINet

E usar essa função para selecionar o certificado assim como digitar a senha do mesmo:

function TForm1.GetCertificado: Boolean;
var
  Store : IStore3;
  CertsLista, CertsSelecionado : ICertificates2;
  CertDados : ICertificate;
  lSigner : TSigner;
  lSignedData : TSignedData;
begin
  Result := False;
  Store := CoStore.Create;
  Store.Open(CAPICOM_CURRENT_USER_STORE, 'My', CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

  CertsLista := Store.Certificates as ICertificates2;
  CertsSelecionado := CertsLista.Select('Certificado(s) Digital(is) disponível(is)', 'Selecione o Certificado Digital para uso no aplicativo', false);

  if not(CertsSelecionado.Count = 0) then
  begin
    CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;
    { Configura o objeto responsável por fazer a assinatura,
      informando qual é o certificado a ser usado e o conteúdo a ser assinado }
    lSigner := TSigner.Create(self);
    lSigner.Certificate := CertDados;
    lSignedData := TSignedData.Create(self);
    lSignedData.Content := ' ';

    { Solicita a senha }
    lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BASE64);

    Result := True;

    lSignedData.Free;
    lSigner.Free;
  end;
end;


Meu form de teste ficou assim:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CAPICOM_TLB, JwaWinCrypt, WinINet, StdCtrls, Buttons;

type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
private
function GetCertificado: Boolean;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if GetCertificado then
ShowMessage('ok');
end;

function TForm1.GetCertificado: Boolean;
var
Store : IStore3;
CertsLista, CertsSelecionado : ICertificates2;
CertDados : ICertificate;
lSigner : TSigner;
lSignedData : TSignedData;
begin
Result := False;
Store := CoStore.Create;
Store.Open(CAPICOM_CURRENT_USER_STORE, 'My', CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

CertsLista := Store.Certificates as ICertificates2;
CertsSelecionado := CertsLista.Select('Certificado(s) Digital(is) disponível(is)', 'Selecione o Certificado Digital para uso no aplicativo', false);

if not(CertsSelecionado.Count = 0) then
begin
CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;
{ Configura o objeto responsável por fazer a assinatura,
informando qual é o certificado a ser usado e o conteúdo a ser assinado }
lSigner := TSigner.Create(self);
lSigner.Certificate := CertDados;
lSignedData := TSignedData.Create(self);
lSignedData.Content := ' ';

{ Solicita a senha }
lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BASE64);

Result := True;

lSignedData.Free;
lSigner.Free;
end;
end;

end.

Responder

Mais Posts

Deve ser algo perto do trecho
 FConfiguracoes.Certificados.GetCertificado; 
Responder

01/11/2012

Luciano Santos

Desculpa a dúvida, mas, na linha:

CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;


O typecast em CertDados é ICertificate2, mesmo, ou ICertificate, conforme seu tipo declarado?

De qualquer forma, penso eu, deve ser ou ICertificate ou ICertificates2 (plural), não?
Não sei, talvez, só se tiver ICertificate2 (singular) declarado na própria biblioteca.
Vê, aí.

Abraços!
Responder

01/11/2012

Luciano Santos

Desculpa a dúvida, mas, na linha:

CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;


O typecast em CertDados é ICertificate2, mesmo, ou ICertificate, conforme seu tipo declarado?

De qualquer forma, penso eu, deve ser ou ICertificate ou ICertificates2 (plural), não?
Não sei, talvez, só se tiver ICertificate2 (singular) declarado na própria biblioteca.
Vê, aí.

Abraços!
Responder
Depende da necessidade, pra o que ela precisa dessa forma funciona. Em outras situações o próprio CertDados poderia ser ICertificate2, mas como ela só vai usar para mostrar os certificados do Windows, selecionar um em seguida solicitar a senha, ou seja, ela quer somente pra uma segurança interna, não vai assinar nada, fiz dessa forma por que ao usar o lSigner.Certificate o tipo tem que ser o ICertificate.
Você está precisando de algo parecido e está dando problema?

Desculpa a dúvida, mas, na linha:

CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;


O typecast em CertDados é ICertificate2, mesmo, ou ICertificate, conforme seu tipo declarado?

De qualquer forma, penso eu, deve ser ou ICertificate ou ICertificates2 (plural), não?
Não sei, talvez, só se tiver ICertificate2 (singular) declarado na própria biblioteca.
Vê, aí.

Abraços!
Responder

01/11/2012

Luciano Santos

Na verdade, ja que você perguntou, estou precisando de umas dicas de playing via stream, conforme coloquei numa questão que ninguém respondeu :-(

http://www.devmedia.com.br/forum/player-atraves-de-streaming-ao-inves-de-arquivo/427614

Será que você poderia fazer umas ideias/dicas?


Quanto ao typecast, só estava falando que o tipo ICERTIFICATE2 não existe ou só foi declarado internamente na biblioteca; os tipos que você usou foram ICERTIFICATE e ICERTIFICATES2; não vi ICERTIFICATE2 e achei que poderia se um erro de typecasting ou um erro de digitação, mas deixa para lá...

Se puderes me ajudar em minha questão, agradeceria bastante...

Abçs!
Responder

01/11/2012

Luciano Santos

Na verdade, ja que você perguntou, estou precisando de umas dicas de playing via stream, conforme coloquei numa questão que ninguém respondeu :-(

http://www.devmedia.com.br/forum/player-atraves-de-streaming-ao-inves-de-arquivo/427614

Será que você poderia fazer umas ideias/dicas?


Quanto ao typecast, só estava falando que o tipo ICERTIFICATE2 não existe ou só foi declarado internamente na biblioteca; os tipos que você usou foram ICERTIFICATE e ICERTIFICATES2; não vi ICERTIFICATE2 e achei que poderia se um erro de typecasting ou um erro de digitação, mas deixa para lá...

Se puderes me ajudar em minha questão, agradeceria bastante...

Abçs!
Responder
Você baixou os arquivos e registou a dll?
Acabei de testar em outra máquina, e em duas versões do Delphi (7 e XE), com certificado A3 e A1 e compilou normalmente, mostrou a lista dos certificados e solicitou a senha.
O ICertificate2 faz parte da CAPICOM, então no uses do form tem que ter: CAPICOM_TLB.
Verifica esses passos e dá um retorno se ocorrer algum problema.

Na verdade, ja que você perguntou, estou precisando de umas dicas de playing via stream, conforme coloquei numa questão que ninguém respondeu :-(

http://www.devmedia.com.br/forum/player-atraves-de-streaming-ao-inves-de-arquivo/427614

Será que você poderia fazer umas ideias/dicas?


Quanto ao typecast, só estava falando que o tipo ICERTIFICATE2 não existe ou só foi declarado internamente na biblioteca; os tipos que você usou foram ICERTIFICATE e ICERTIFICATES2; não vi ICERTIFICATE2 e achei que poderia se um erro de typecasting ou um erro de digitação, mas deixa para lá...

Se puderes me ajudar em minha questão, agradeceria bastante...

Abçs!
Responder
Uau! Acho que é isso mesmo !!! Deixei o certificado no escritório, na 2.a feira vou testar... Obrigada =]
Responder
Show de bola ! O certificado digital do meu marido estava em casa então consegui testar... Muito obrigada Claudiadnh !

Adaptei o Form1 do AcbrNfe2 além de incluir a validação de Data + CPF / CNPJ do emitente e ficou assim:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if GetCertificadoNovo then
    showmessage('ok')
  else
    showmessage('erro');
end;

function TForm1.GetCertificadoNovo: Boolean;
var
  Store : IStore3;
  CertsLista, CertsSelecionado : ICertificates2;
  CertDados : ICertificate;
  lSigner : TSigner;
  lSignedData : TSignedData;
begin
  Result := False;
  Store := CoStore.Create;
  Store.Open(CAPICOM_CURRENT_USER_STORE, 'My', CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

  CertsLista := Store.Certificates as ICertificates2;
  CertsSelecionado := CertsLista.Select('Certificado(s) Digital(is) disponível(is)', 'Selecione o Certificado Digital para uso no aplicativo', false);

  if not(CertsSelecionado.Count = 0) then
  begin
    CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;
    if CertDados.ValidFromDate > Now then
    begin
      showmessage('certificado não liberado. aguardar '+datetostr(CertDados.ValidFromDate));
      exit;
    end;
    if CertDados.ValidToDate < Now then
    begin
      showmessage('certificado expirado');
      exit;
    end;

    if Pos(edtEmitCNPJ.text,CertDados.SubjectName) = 0 then
    begin
      showmessage('certificado pertencente a outra empresa / pessoa'+chr(13)+CertDados.SubjectName);
      exit;
    end;

    { Configura o objeto responsável por fazer a assinatura,
    informando qual é o certificado a ser usado e o conteúdo a ser assinado }
    lSigner := TSigner.Create(self);
    lSigner.Certificate := CertDados;

    lSignedData := TSignedData.Create(self);
    lSignedData.Content := ' ';


    { Solicita a senha }
    lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BASE64);

    Result := True;

    lSignedData.Free;
    lSigner.Free;
  end;
end;
Responder
Que bom que deu certo. :)
Passei meio na correria e acabei colocando coisa a mais. Alguns arquivos que passei não são necessários, depois que fui ler e percebi, é que retirei de um outro código meu e montei a função, e no outro código precisava de tudo que foi postado.
Responder

09/11/2012

Thiago Gobatti

Boa noite.
Muito boa sua dica consegui fazer a leitura do certificado.
Porem precisava da ajuda para assinar um documento podendo ser JPG ou PDF, como posso fazer isso?

obrigado.
Responder
Olá Claudiadnh, tudo bem?
Trabalho com desenvolvimento de software na área da saúde e estou precisando realizar a assinatura digital de documentos, por exemplo, evolução de enfermagem de um paciente.
Não sei se você teria algum exemplo de como acessar a leitora do cartão, buscar o certificado digital e assinar as informações.

Desde já muito obrigado!
Responder
Oi gente.
Sobre assinar outros tipos de documentos, como JPG e PDF, essa forma que eu passei não se aplica, pois qualquer alteração nos bytes dos arquivos desses tipos invalidará os mesmos.
Pelo que estou percebendo, vocês querem adicionar a imagem de uma assinatura, e não o texto gerado pela assinatura digital.
A rotina que eu passei serve apenas para carregar os certificados, solicitar a senha e caso precise, assinar um arquivo XML.
O jeito que vocês precisam, é completamente outra coisa, vocês teriam que digitalizar a assinatura do responsável, transformar em imagem, e "concatenar" essa imagem com os documentos de vocês. No caso a rotina serviria apenas pra chamar o certificado e solicitar a senha, somente para verificação se a pessoa que está tentando fazer tal operação sabe a senha do certificado digital da empresa.
Infelizmente não posso ajudar com relação a esse outro tipo de assinatura, vamos ver se mais colegas do fórum já passaram por essa experiência.
Responder

20/12/2012

Dionata Araujo

Essa é parte da rotina que tenho para ler o certificado digital através do token feita em Delphi Xe2.
{

OE_Util:=createoleobject('CAPICOM.Utilities.1');
store := TStore.Create (self);
store.Open( CAPICOM_SMART_CARD_USER_STORE, 'Root', CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
certs := TCertificates.Create(self);
certs.ConnectTo(store.Certificates as ICertificates2);

cert := TCertificate.Create(self);
for i := 1 to certs.Count do
begin
ov := (certs.Item [i]);
cert.ConnectTo (IDispatch (ov) as ICertificate2);

Memo1.Lines.Add('Versão do certificado--->' + IntToStr(cert.Version));
Memo1.Lines.Add('Nº serial do certificado--->' + cert.SerialNumber);
Memo1.Lines.Add('Autoridade certificadora--->' + cert.SubjectName);
Memo1.Lines.Add('Nº remoto--->' + cert.RemoteMachineName);
Memo1.Lines.Add('ThumbPrint--->' + cert.Thumbprint);
Memo1.Lines.Add('IssuerName--->' + cert.IssuerName);
Memo1.Lines.Add('Informação1--->' + cert.GetInfo(CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME));
Memo1.Lines.Add('Informação2--->' + cert.GetInfo(CAPICOM_CERT_INFO_SUBJECT_EMAIL_NAME));
Memo1.Lines.Add('Informação3--->' + cert.GetInfo(CAPICOM_CERT_INFO_ISSUER_DNS_NAME));


Memo1.Lines.Add('HASH CODE---->' +IntToStr(cert.GetHashCode));
Memo1.Lines.Add('Tamanho da chave publica--->' + IntToStr(cert.PublicKey.Length));
Memo1.Lines.Add('Algoritimo de validação--->' + cert.PublicKey.Algorithm.Value);
strstring:= OE_Util.BinaryToHex(Cert.PublicKey.EncodedKey.Value[CAPICOM_ENCODE_BINARY]);
Memo1.Lines.Add('Valor da Chave Privada em string---->' + strstring);
Memo1.Lines.Add('-------------------------------------');
Memo1.Lines.Add('CHAVE PUBLICA BASE 64---->' + cert.PublicKey.EncodedKey.Value[CAPICOM_ENCODE_BASE64]);
Memo1.Lines.Add('-------------------------------------');


Memo1.Lines.Add('conteudo do cerificado');
Memo1.Lines.Add(cert.Export(CAPICOM_ENCODE_BASE64));

if cert.HasPrivateKey then
begin
Memo1.Lines.add('CERTIFICADO COM CHAVE PRIVADA');
if (cert.IsValid.Result) then
begin
Memo1.Lines.Add('CERTIFICADO VALIDO');
//validar no web service
end
else
Memo1.Lines.Add('CERTIFICADO INVÁLIDO')
end
else
begin
Memo1.Lines.add('CERTIFICADO SEM CHAVE PRIVADA');
if (cert.IsValid.Result) then
Memo1.Lines.Add('CERTIFICADO VALIDO')
else
Memo1.Lines.Add('CERTIFICADO INVÁLIDO');
end;

Memo1.Lines.Add('-------------------------------------------------------');
}

Como faço para pegar o valor da assinatura que esta dentro do token
Responder

13/02/2013

Antonio Caser

Depende da necessidade, pra o que ela precisa dessa forma funciona. Em outras situações o próprio CertDados poderia ser ICertificate2, mas como ela só vai usar para mostrar os certificados do Windows, selecionar um em seguida solicitar a senha, ou seja, ela quer somente pra uma segurança interna, não vai assinar nada, fiz dessa forma por que ao usar o lSigner.Certificate o tipo tem que ser o ICertificate.
Você está precisando de algo parecido e está dando problema?

Desculpa a dúvida, mas, na linha:

CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;


O typecast em CertDados é ICertificate2, mesmo, ou ICertificate, conforme seu tipo declarado?

De qualquer forma, penso eu, deve ser ou ICertificate ou ICertificates2 (plural), não?
Não sei, talvez, só se tiver ICertificate2 (singular) declarado na própria biblioteca.
Vê, aí.

Abraços!


=======

Claudia,

estou com problema com o meu certificado, que exportei sem a opção "chave privada" que estava apagada, não disponível, ao instalar ele não aparece na aba "pessoal" do navegador IE8(Ferramentas/Opções de Internet/Conteúdo/Certificados), mas verificando o certificado instalado pelo "certmgr.msc", consta todas as informações inclusive a "Chave privada" está lá intacta, mas não consigo exportar para a extensão ".PFX" que só exporta para ".CER".

Tem como recuperar a "Chave privada"?

Obs: o PC foi formatado, só tenho o certificado ".CER".

Muito obrigado.

Antonio Caser
Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários. Para saber mais sobre o uso de cookies,
consulte nossa política de privacidade. Ao continuar navegando em nosso site, você concorda com a nossa política.

Aceitar