Assinatura Digital em qualquer rotina do sistema
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
Melhor post
Claudia Nogueira
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.
Mais Respostas
Powerlog Tecnologia
01/11/2012
FConfiguracoes.Certificados.GetCertificado;
Luciano Santos
01/11/2012
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!
Luciano Santos
01/11/2012
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 Nogueira
01/11/2012
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!
Luciano Santos
01/11/2012
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!
Luciano Santos
01/11/2012
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!
Claudia Nogueira
01/11/2012
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!
Powerlog Tecnologia
01/11/2012
Powerlog Tecnologia
01/11/2012
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;
Claudia Nogueira
01/11/2012
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.
Thiago Gobatti
01/11/2012
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.
Anderson Zielke
01/11/2012
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!
Claudia Nogueira
01/11/2012
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.
Dionata Araujo
01/11/2012
{
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
Antonio Caser
01/11/2012
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
Luiz Junior
01/11/2012
Gunther Morais
01/11/2012
[Error] form_principal.pas(111): Incompatible types: 'IStore' and 'IStore3'
[Error] form_principal.pas(123): Incompatible types: 'ICertificate' and 'ICertificate2'
[Error] form_principal.pas(128): Incompatible types: 'ISigner' and 'ISigner2'
Jefferson Taquete
01/11/2012
poderia colocar os links dos arquivos novamente pois não estou conseguindo baixá-los.
Obrigado.
Powerlog Tecnologia
01/11/2012
Importar a capicom.dll - Para isso, vá no menu Projects - Import Type Library - Add - Escolha o Arquivo c:\WINDOWS\system32\capicom.dll (Windows XP) - Create Unit. Será criado uma unit com o nome CAPICOM_TLB.
Adicione as units WinINet, CAPICOM_TLB, JwaWinCrypt no uses da sua unit.
Extraído de [url]http://www.forumweb.com.br/foruns/topic/74776-nota-fiscal-eletronica-nfe-resolvido/[/url]
Powerlog Tecnologia
01/11/2012
Cliente formatou a máquina, já instalei as DLLs, reinstalei o CAPICOM e continua a mensagem.
Alguma dica ?
Rogério Hitachi
01/11/2012
Por favor, estou com um grande problema...
Eu olhei as postagens no fórum e aparentemente achei que seria simples assinar digitalmente um arquivo .XML, mas não estou conseguindo e o prazo está se esgotando.
Quando chega na linha :
msg := lSignedData.Sign( lSigner as ISigner2 , false, CAPICOM_ENCODE_BASE64);
Dá o erro:
"Interface not supported"
Alguém poderia me ajudar??????
Obrigado.
Segue o código completo:
procedure TForm1.Button3Click(Sender: TObject);
var
lSigner : TSigner;
lSignedData : TSignedData;
fs : TFileStream;
i, qt : integer;
ch : PChar;
msg, content : WideString;
store : TStore;
certsss : TCertificates;
cert : TCertificate;
ov : OleVariant;
begin
{ Abre o arquivo original para obter dele o conteúdo a ser assinado }
fs := TFileStream.Create (edFileName.Text, fmOpenRead);
New (ch);
repeat
qt := fs.Read(ch^, 1);
if (qt > 0) then
content := content + ch^;
until qt = 0;
fs.Free;
Dispose (ch);
store := TStore.Create (self);
store.Open (CAPICOM_CURRENT_USER_STORE, 'MY', CAPICOM_STORE_OPEN_READ_WRITE);
certsss := TCertificates.Create(self);
certsss.ConnectTo(store.Certificates as ICertificates2);
cert := TCertificate.Create(self);
for i := 1 to certsss.Count do
begin
ov := (certsss.Item [i]);
cert.ConnectTo (IDispatch (ov) as ICertificate2);
lSigner := TSigner.Create(self);
lSigner.Certificate := ICertificate2 ( cert.DefaultInterface as ICertificate2);
lSignedData := TSignedData.Create(self);
lSignedData.Content := content;
{ Efetivamente assina o conteúdo }
try
msg := lSignedData.Sign( lSigner as ISigner2 , false, CAPICOM_ENCODE_BASE64);
except on E: Exception do
showmessage ('Erro : '#13#13 + E.Message);
end;
{ Cria um novo arquivo e grava nele o resultado da assinatura }
fs := TFileStream.Create (edFileName.Text, fmCreate);
for qt := 1 to Length (msg) do
fs.Write(msg[qt], 2);
fs.Free;
lSignedData.Free;
lSigner.Free;
end;
end;
Altec Ltda.
01/11/2012
Nilson Jr
01/11/2012
os links do inicio do post estão expirados ...teria como disponibilizar links validos por favor ..
Estou precisando de implementar assinaturas digitais em transferencia de bens do patrimonio, entre s a origem e destino do bem;
agradeco antecipadamente ...
Reynaldo Bittencurt
01/11/2012
como faz baixa esse arquivor tem como vc mi manda ele po meu e-mail reynaldobittencurt@hotmail.com
http://www.cdnweb.com.br/capicom_dll.rar Descompactar na System32 e depois executar o CapiCom.bat para registrar a dll.
http://www.cdnweb.com.br/capicom_tbl.rar Descompactar na pasta Imports do Delphi.
http://www.cdnweb.com.br/win32api.rar Descompactar em algum lugar e adicionar no LibraryPath do Delphi.
Reynaldo Bittencurt
01/11/2012
Ademir Lusa
01/11/2012
NO USES:
ACBrCAPICOM_TLB, JwaWinCrypt, WinINet,
NO COMANDO COLOQUE
TESTA SE O CERTIFICADO É DO CLIENTE:
if Pos(RemoveChar(dm.SDS_EmpresaCNPJ.text), DM.ACBrNFe1.Configuracoes.Certificados.GetCertificado.SubjectName) = 0 then
begin
showmessage('Certificado pertencente a outra empresa / pessoa'+chr(13)+DM.ACBrNFe1.Configuracoes.Certificados.GetCertificado.SubjectName);
exit;
end;
TESTA A DATA DE VENCIMENTO DO CERTIFICAO:
IF DM.ACBrNFe1.Configuracoes.Certificados.DataVenc < Now then
begin
showmessage('Certificado vencido (data de validade expirada)');
Exit;
end;
Reynaldo Bittencurt
01/11/2012
voce poder mi da um ajuda
como fazer assinaturas digitais das aplicações feita em Delphi
Toni Rodriguez
01/11/2012
Toni Rodriguez
01/11/2012
Toni Rodriguez
01/11/2012
Toni Rodriguez
01/11/2012
Toni Rodriguez
01/11/2012
Powerlog Tecnologia
01/11/2012
https://mfi.re/folder/bwu07uubc5mrx/Delphi
Mas de qualquer forma quem baixar o ACBr já terá essas opções ao instalar a NFe
Nedson Gomes
01/11/2012
Elvys
01/11/2012
{ Solicita a senha }
lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BASE64);
A função lSignedData.Sign, chamaria um formulário para digitação da senha? Não consegui fazer funcionar desta forma.
Outra questão é: Alguém conseguiu ou sabe de outra forma para assinar digitalmente um arquivo pdf, doc ou imagem?
Gustavo Novaes
01/11/2012
Com esse CAPICOM é possível assinar relatórios emitidos via QuickReport ou report Builder no delphi?
Gerasoft Ltda
01/11/2012
Alguém passou por isso ?
att.