Assinatura Digital em qualquer rotina do sistema
01/11/2012
0
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]
Powerlog Tecnologia
Post mais votado
01/11/2012
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.
Claudia Nogueira
Mais Posts
01/11/2012
Powerlog Tecnologia
FConfiguracoes.Certificados.GetCertificado;
01/11/2012
Luciano Santos
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!
01/11/2012
Luciano Santos
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!
01/11/2012
Claudia Nogueira
Você está precisando de algo parecido e está dando problema?
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!
01/11/2012
Luciano Santos
https://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!
01/11/2012
Luciano Santos
https://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!
01/11/2012
Claudia Nogueira
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.
https://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!
02/11/2012
Powerlog Tecnologia
02/11/2012
Powerlog Tecnologia
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;
02/11/2012
Claudia Nogueira
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.
09/11/2012
Thiago Gobatti
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.
15/11/2012
Anderson Zielke
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!
16/11/2012
Claudia Nogueira
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.
20/12/2012
Dionata Araujo
{
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
13/02/2013
Antonio Caser
Você está precisando de algo parecido e está dando problema?
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
Clique aqui para fazer login e interagir na Comunidade :)