Mostrando postagens com marcador CAPICOM. Mostrar todas as postagens
Mostrando postagens com marcador CAPICOM. Mostrar todas as postagens

18 de julho de 2012

Assinando documentos XML com CAPICOM e Delphi

A Microsoft disponibiliza para o Windows uma biblioteca com tecnologia COM para tratar a criação e manipulação de arquivos XML. A biblioteca, chamada MSXML, está atualmente na versão 6 e suporta também transformações XSLT e validação através de esquemas XSD. Em apenas uma das versões (o MSXML5), foram incluídos ainda recursos para fazer assinatura digital de XMLs.

A versão 5 foi distribuída exclusivamente com o Microsoft Office para que os desenvolvedores dessa plataforma pudessem assinar XMLs. No entanto, uma busca na internet revela que a biblioteca é amplamente utilizada fora desse contexto.

Isto é uma boa notícia para quem usa Delphi (ou outra linguagem que suporte COM) pois o MSXML5, em associação com o CAPICOM, facilita bastante a tarefa de assinar XMLs. Neste post eu mostro como realizar este processo, considerando que você já tem montado o XML que quer assinar. O quadro abaixo mostra parte do XML de uma Nota Fiscal que vou usar como exemplo:
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
<infNFe Id="NFe3508059978" versao="2.00">
<cUF>35</cUF>
<cNF>518005127</cNF>
<natOp>Venda a vista</natOp>
<mod>55</mod>
<serie>1</serie>
<dEmi>2012-05-06</dEmi>
<tpAmb>2</tpAmb>
</infNFe>
</NFe>
</enviNFe>

A primeira providência é importar os fontes dos ActiveX MSXML5 e CAPICOM para podermos utilizá-los no projeto Delphi. Há um resumo de como fazer essa importação neste endereço; para o MSXML5, a descrição da Type Library é Microsoft XML, v5.0. Ambos os fontes gerados devem ser incluídos na cláusula uses da unit que for fazer a assinatura.

Obviamente, vamos precisar de um certificado digital para realizar a assinatura. Utilizando o CAPICOM, podemos acessar o Certificate Store do Windows e localizar um apropriado, que tenha sido gerado para sua empresa. No entanto, as interfaces disponíveis no MSXML5 exigem que você informe um Certificate Store com o certificado que será utilizado, bem como sua cadeia de validação, se for necessário. Este passo extra é mostrado no quadro abaixo.
var store : IStore3;
cert : TCertificate;
lKey : IPrivateKey;
begin
cert := getCert;
lKey := Cert.PrivateKey;

{ Monta um Store em memória com o Certificado obtido antes }
store := CoStore.Create;
store.Open(CAPICOM_CURRENT_USER_STORE, 'My', CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
store.Add(cert.DefaultInterface);
{ ... }

A função GetCert utilizada acima é minha e segue as instruções descritas no post sobre acesso ao Certificate Store com CAPICOM. De resto, o código apenas cria um Store em memória e adiciona a ele o certificado encontrado. O trecho também salva a chave privada deste certificado, informação que será usada mais adiante para gerar a assinatura em si.

A seguir, precisamos preparar o XML do exemplo para receber a assinatura. É que a interface do MSXML5 responsável por essa etapa se baseia num nó Signature do XML. Esse nó descreve as transformações pelas quais o XML deve ser submetido antes de ser de fato assinado. O nó Signature deve ser criado como mostrado abaixo:
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
{ ... }
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe3508059978">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue></SignatureValue>
</Signature>
</NFe>
</enviNFe>

Como podemos ver acima, o nó também deixa reservado um local para receber o hash (DigestValue) e outro para a própria assinatura (SignatureValue), que serão preenchidos automaticamente. A única parte variável do bloco preparado acima é o atributo URI da tag Reference, valor que reflete a identificação da Nota Fiscal contida no XML. Ou seja, deve-se montar o valor desse atributo a partir do valor do atributo Id da tag infNFe, precedendo este valor com o sinal #. Como o próprio nome diz, essa parte do XML faz referência ao nó (e seus filhos) que será resguardado pela assinatura digital.

Uma vez que o XML está preparado, podemos partir para a assinatura propriamente dita, o que é conseguido através da interface IXMLDigitalSignature do MSXML5. Então, precisamos criar uma instância dela e lhe fornecedor os dados para a assinatura:
var {...}
xmlDoc: IXmlDomDocument3;
noSignature : IXMLDOMElement;
xmlSign : IXMLDigitalSignature;
xmlDsigKey: IXMLDSigKey;
begin
{...}
{ Monta o XML e prepara a tag Signature }
xmlDoc := PreparaXML ();
noSignature := EncontraNodeSignature (xmlDoc);

if (noSignature <> Nil) then begin
xmlSign := CoMXDigitalSignature50.Create;
xmlSign.signature := noSignature;
xmlSign.store := store;

{ Monta a chave com o tipo exigido pelo método Sign }
xmlDsigKey := xmlSign.createKeyFromCSP(lKey.ProviderType, lKey.ProviderName, lKey.ContainerName, 0);
{ Assina o XML }
xmlSign.sign(xmlDsigKey, NOKEYINFO);
{...}
end;
end;

Como podemos ver no trecho de código acima, o IXMLDigitalSignature precisa que indiquemos qual é o nó Signature do nosso XmlDomDocument e o Certificate Store que construímos no início do post. Agora, temos que chamar o método sign para completar o serviço. Para funcionar, ele precisa de algumas informações baseadas na chave privada do certificado. No exemplo acima, utilizei a chave recuperada a partir do certificado para criar uma instância da interface IXMLDSigKey contendo as informações necessárias.

O segundo parâmetro da função sign determina como os dados da chave serão incluídos na estrutura do XML. No exemplo, usei o valor NOKEYINFO para que tais dados não sejam incluídos automaticamente.

Após chamar a função sign, as tags que deixamos reservadas no nó Signature são automaticamente calculadas e preenchidas. Finalizando, para que o XML fique no padrão exigido para Notas Fiscais pela Receita Federal, só falta incluir um nó com os dados do certificado usado para assinar. Mostrei como fazer isso no post Certificado Digital para inclusão no XML com CAPICOM e Delphi.

16 de maio de 2012

Preparando o Certificado Digital para inclusão no XML com CAPICOM e Delphi

Há algum tempo, publiquei uma série de posts sobre a manipulação de XMLs e a criação de assinatura digital para eles. Como a plataforma .NET da Microsoft traz classes prontas para realizar o grosso das tarefas envolvidas, eu usei o C# para montar os exemplos contidos naqueles posts.

Mas muita gente não pode usar a solução com .Net, principalmente quem já têm aplicações desenvolvidas em outras linguagens. Algumas dessas pessoas entraram em contato pra saber como fazer esse mesmo procedimento usando a biblioteca de criptografia da Microsoft - o CAPICOM. Uma dúvida bastante frequente é relativa ao conteúdo a ser inserido na tag X509Certificate do XML assinado. O quadro abaixo mostra o trecho de um XML assinado de Nota Fiscal Eletrônica que inclui a tag em questão:
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
<infNFe Id="NFe3508059978" versao="2.00">
<cUF>35</cUF>
<cNF>518005127</cNF>
<natOp>Venda a vista</natOp>
<mod>55</mod>
<serie>1</serie>
<dEmi>2012-05-06</dEmi>
<tpAmb>2</tpAmb>
</infNFe>
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe3508059978"
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>4aXU7m8rl14ALy6X...=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>Igq7eI/Fy3PyjjSW...=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIGxDCCBaygAwIBAgIIN6q4...=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</NFe>
</enviNFe>

Como podemos ver, a tag X509Certificate é parte da estrutura que traz as informações sobre a chave usada pela assinatura e é incluída no fim do XML, junto com a área reservada para a assinatura em si. O valor armazenado na X509Certificate descreve o certificado usado na assinatura, codificado na Base64. Esse valor representa a chave do certificado e é parte imprescindível para a validação do documento XML, isso é, ele ajuda a garantir que o XML não foi adulterado depois de ter sido assinado.

E como calcular esse valor com CAPICOM? Após recuperar o certificado digital de acordo com as instruções do post Acessando o Certificate Store do Windows com CAPICOM, podemos conseguir o conteúdo desse certificado já na Base64 em um único comando:
var cert : TCertificate;
certBase64 : WideString;
begin
{ ... }
certBase64 := cert.Export(CAPICOM_ENCODE_BASE64);
{ ... }
A função export da interface ICertificate2 aceita como parâmetro o tipo de codificação que se deseja como resultado da exportaçao. Os valores permitidos para esse parâmetros são os definidos no tipo enumerado CAPICOM_ENCODING_TYPE. Ele pode assumir basicamente dois tipo de codificação : a Base64 ou a informação binária pura, sem codificação.

O código utilizado no exemplo - CAPICOM_ENCODE_BASE64 - faz a exportação de todas as informações necessárias para inclusão na tag X509Certificate do XML assinado. Há, no entanto, um detalhe no qual é preciso prestar atenção: o texto exportado está quebrado em diversas linhas.
MIIGNjCCBR6gAwIBAgIITDgm4uwI+60wDQYJKoZIhvcNAQEFBQAwTDELMAkGA1UE
BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxKDAmBgNVBAMTH1NFUkFTQSBDZXJ0
aWZpY2Fkb3JhIERpZ2l0YWwgdjEwHhcNMTEwNzA3MTMxMDA0WhcNMTIwNzA2MTMx
MDA0WjCB7jELMAkGA1UEBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxFDASBgNV
BAsTCyhFTSBCUkFOQ08pMRgwFgYDVQQLEw8wMDAwMDEwMDE5NjExNzIxFDASBgNV
BAsTCyhFTSBCUkFOQ08pMRQwEgYDVQQLEwsoRU0gQlJBTkNPKTEUMBIGA1UECxML
.
.
.
aXRhbC5jb20uYnIvc2VyYXNhY2R2MTANBgkqhkiG9w0BAQUFAAOCAQEAY8NBFO6e
kPTHirS8DHnlsx1kTJfmsHoUR1QgnDMNdChQjW7ctAn5nIpPYXdhf26om+Us80D/
5RA2iXHhXFT5eL7Crqq0DQ73zWbdn8e81dIDFqYjxIt4LBMy4CO0lJeiT9YHkmYB
XSuADpElqwXA0rzx7bBeIOzuVUGMoYQBduViByI813XIQ2i86Z9VgRLO5KuPUNPn
0RkZS2rSpX1/wLkef8ura++dZEYmbVWpu3g2yCLQJfCArYy/fzsIDwBKruSWnY/O
NK/1AgUaceVAcxxvVmuECwCBqtpfmHqAOXC/uEOXiKefF7L++j0Xc+Okew1SMkHJ
sNNJ+AcX4VfQrw==

Como o conteúdo da tag X509Certificate deve estar numa única linha, o texto retornado pelo export deve ser tratado, removendo-se os espaços em branco do fim e as quebras de linha:
certBase64 := Trim (ReplaceStr (certBase64, #13#10, ''));

O valor da variável certBase64 agora pode ser incluído sem problemas como conteúdo da tag X509Certificate em seu XML assinado.

17 de julho de 2009

Verificando assinaturas digitais com CAPICOM

Continuando a série sobre Certificados e assinaturas digitais usando a biblioteca CAPICOM, falo agora sobre como verificar se uma assinatura é válida, isto é, se os dados que foram assinados não foram adulterados de alguma forma.

Vou usar aqui o mesmo exemplo do post sobre assinatura digital com CAPICOM. Naquele exemplo, assinei o conteúdo de um arquivo e salvei o resultado num outro arquivo. Ao assinar, programei o CAPICOM para incluir na assinatura todo o conteúdo assinado.

Neste caso, para verificar se a assinatura é válida, é preciso apenas instanciar a mesma classe que foi usada para assinar: a TSignedData. Diferentemente do processo de assinatura, a validação não exige configuração extra do TSignedData pois a chave pública necessária já foi incluída na própria assinatura. O código abaixo mostra a validação da assinatura gerada no post anterior:
var lSignedData: TSignedData;
fs : TFileStream;
qt : integer;
ch : PWideChar;
msg : WideString;
ok : boolean;
begin
fs := TFileStream.Create (edMsgFile.Text, fmOpenRead);
New (ch);
repeat
qt := fs.Read(ch^, 2);
if qt > 0 then
msg := msg + ch^;
until qt = 0;
fs.Free;
Dispose (ch);

lSignedData := TSignedData.Create(self);

try
ok := false;
lSignedData.Verify (msg, false, CAPICOM_VERIFY_SIGNATURE_ONLY);
msg := lSignedData.Content;
ok := true;
except
on exc: Exception do
ShowMessage (exc.Message);
end;

lSignedData.Free;

if ok then
ShowMessage ('Conteúdo validado com sucesso !');
end;

Na primeira parte do código, leio o arquivo com a assinatura e jogo esse conteúdo para a variável msg. Lembre-se de que a assinatura foi gerada num WideString e que, portanto, cada caractere é representado por 2 bytes. Por isso, a leitura é feita usando um WideChar e lendo 2 bytes por vez antes do valor ser concatenado ao WideString com a assinatura.

Depois, crio a instância do TSignedData e apenas chamo sua função Verify para realizar a validação. O primeiro parâmetro desta função é o conteúdo assinado (que foi lido do arquivo); o segundo parâmetro tem o nome de Detached, significando "solto" ou "desprendido" em referência ao fato de indicar se o conteúdo original está "desprendido" ou se foi embutido na assinatura - por isso passo false nele: o conteúdo não está desprendido já que fiz a assinatura pedindo para inserir o conteúdo. O último parâmetro é um indicador do quê será validado: somente a assinatura ou validar também o certificado.

Se tudo ocorreu bem na verificação, a propriedade Content da classe TSignedData agora possui o mesmo conteúdo que foi originalmente assinado, isto é, este processo também pode ser usado para criptografar os dados e de quebra saber se eles não foram adulterados já que para assiná-lo é preciso ter a chave privada e só você deveria ter esta informação.

No caso de um erro acontecer na validação, uma exceção é levantada. Então, incluí o processo de validação num bloco try-except para poder tratar a mensagem retornada.

E se a assinatura for gerada sem o conteúdo ? Como validar ? Simples: alimente manualmente a propriedade Content antes de chamar o Verify. Nessa situação, tanto o conteúdo original quanto a assinatura têm que estar presentes para a validação funcionar.

16 de julho de 2009

Assinando documentos com CAPICOM

No meu último post, falei sobre a biblioteca criptográfica da Microsoft - o CAPICOM - e como usá-la para acessar o Certificate Store do Windows, recuperando e processando os certificados digitais registrados. Agora, vou mostrar como usar as classes do CAPICOM para assinar documentos e como verificar se a assinatura de um documento é válida.

Pra começar, é preciso ter um Certificado Digital disponível com a chave privada para que se possa assinar documentos. Se não possuir tal certificado, pode gerar um através do programa makecert da Microsoft. Tenha em mente apenas que o certificado assim gerado não pode assinar documentos oficialmente pois não é fornecido por uma CA (Certification Authority) válida. Um exemplo do makecert pode ser visto no quadro abaixo, onde é criado um certificado pessoal ("My") no Store Current User com validade até 1 de Janeiro de 2010:
makecert -r -pe -n "CN=Minha Empresa" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my

Para assinar um documento, precisaremos trabalhar com 2 classes do CAPICOM:
TSigner que contem as informações sobre quem está assinando um documento, incluindo o Certificado Digital.
TSignedData que permite estabelecer os dados a serem assinados. A verificação de uma assinatura também pode ser feita com essa classe.

O trecho de código abaixo carrega um arquivo, assina-o baseado num Certificado Digital e grava o conteúdo assinado num outro arquivo. Veja o post anterior para saber como gerar os fontes associados ao CAPICOM e como encontrar um Certificado no Store.
procedure TForm1.Assina (cert: TCertificate);
var lSigner : TSigner;
lSignedData : TSignedData;
fs : TFileStream;
qt : integer;
ch : PChar;
msg, content : WideString;
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);

{ 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 := cert.DefaultInterface;

lSignedData := TSignedData.Create(self);

lSignedData.Content := content;
{ Efetivamente assina o conteúdo }
msg := lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BASE64);

{ Cria um novo arquivo e grava nele o resultado da assinatura }
fs := TFileStream.Create (edMsgFile.Text, fmCreate);
for qt := 1 to Length (msg) do
fs.Write(msg[qt], 2);

fs.Free;

lSignedData.Free;
lSigner.Free;
end;

Neste código, crio uma instância do TSigner e associo a ele o certificado passado no parâmetro da função. Depois, crio uma instância do TSignedData e alimento sua propriedade Content com o conteúdo lido do arquivo (texto) que será assinado.

Com essa configuração ajustada, posso chamar a função Sign do TSignedData para assinar o conteúdo. O primeiro parâmetro desta função é o TSigner onde informei o certificado digital que tem chave privada. O segundo parâmetro indica se o conteúdo original será incluído na assinatura resultante ou não. Incluir o conteúdo na assinatura resulta uma assinatura muito maior mas o processo de verificação dela permitirá extrair o conteúdo original (desde que, é claro, a assinatura não tenha sido adulterada). Se não incluir o conteúdo na assinatura, o conteúdo terá que estar presente para que se possa executar o processo de validação; em compensação, a assinatura será pequena.

O resultado da função Sign é um WideString contendo a assinatura. No exemplo, pedi que a assinatura inclua o conteúdo original e, então, salvo toda a assinatura num arquivo separado. Como cada caracter do WideString ocupa 2 bytes, o trecho do código que grava em arquivo o resultado da assinatura é obrigado a gravar os 2 bytes por caracter. Mostro no próximo post como validar essa assinatura gerada.

14 de julho de 2009

Acessando o Certificate Store do Windows com CAPICOM

Desde que eu publiquei aqui posts sobre Certificados Digitais usando o framework .Net, várias pessoas me contataram dizendo que não desenvolvem com .Net e perguntando como acessar o Certificate Store do Windows e como assinar documentos digitalmente sem usar o Framework. Já havia falado em outra ocasião mas repito aqui: a solução é usar a biblioteca CAPICOM (Cryptographic Application Programming Interface) da Microsoft, cujo download é gratuito.

Vou mostrar nesse post como utilizar as classes do CAPICOM em Delphi para acessar o Certificate Store do Windows já que esse passo precede a assinatura de documentos - é preciso recuperar um Certificado Digital para realizar a assinatura. No post sobre como trabalhar com o Certificate Store com .NET há mais informações e terminologia sobre o assunto.

Como o CAPICOM é uma biblioteca COM, o primeiro passo é extrair as interfaces e colocá-las na forma de fontes do Delphi. Se ainda não tem os fontes, veja aqui como fazer essa extração e gerá-los. Para usar as classes exportadas, o seu programa deve incluir a unit gerada:
uses CAPICOM_TLB;
Da mesma forma que no .NET, há três classes básicas no CAPICOM para acessar o Store:
TStore que fornece os métodos para acessar o Certificate Store. Há um método Open nessa classe onde se estipula qual parte do Store se quer acessar: store pessoal ("My"), as autoridades certificadoras ("CA"), etc.
TCertificates é uma lista com todos os certificados que atendem os parâmetros especificados ao abrir o Store ou quando se usa a função de seleção Select.
TCertificate representa um certificado e suas propriedades, isto é, se ele está válido, qual é a chave pública, se há uma chave privada disponível e qual é esta chave.

O trecho de código Delphi abaixo abre o Certificate Store "My" da máquina local com privilégio apenas para leitura, recupera todos os certificados encontrados e percorre a lista pesquisando os certificados que são válidos.
var i : integer;
store : TStore;
cert : TCertificate;
certs : TCertificates;
ov : OleVariant;
begin
store := TStore.Create (self);

store.Open (CAPICOM_LOCAL_MACHINE_STORE, 'My', CAPICOM_STORE_OPEN_READ_ONLY);

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);

if cert.HasPrivateKey And
(cert.ValidFromDate <= Now) And
(cert.ValidToDate >= Now) then begin
{ Use o certificado aqui para, por exemplo, assinar um documento. }
end;
end;

store.Close;

cert.Free;
certs.Free;
store.Free;
end;

Algumas observações a respeito desse código:
As classes do CAPICOM foram instanciadas através de seus respectivos construtores Create. Por questão de compatibilidade, a Microsoft mantem na assinatura das funções da interface os tipos de estrutura usadas na primeira versão do CAPICOM. Como estou usando o CAPICOM 2.x, o TCertificates aqui é uma extensão da interface original ICertificates. Para poder usar todos os recursos da nova estrutura, crio na mão uma instância do TCertificates e conecto-a à referência de interface retornada pelo TStore. O mesmo vale para o ICertificate
O TCertificates é uma lista e a propriedade Count indica quantos certificados há nesta lista.
Para acessar um certificado na lista TCertificates use a propriedade Item. Valores válidos para indexar essa propriedade vão de 1 até Count
O mapeamento gerado pelo Delphi para a propriedade Item retorna um valor do tipo OleVariant. Na verdade, ela encapsula uma referência à interface ICertificate2 mas como não é permitido fazer um cast direto para esse tipo, transformo antes o valor retornado pelo Item em um IDispatch. Como o IDispatch é o ancestral de todas as interfaces (em qualquer COM), posso então fazer o cast para o tipo correto, conectá-lo à classe TCertificate e usar normalmente as propriedades do ICertificate2 para verificar se o certificado é válido e tem chave privada que possa ser usada num assinatura digital.
No exemplo acima, acesso apenas os certificados My armazenados na área da máquina local. Se quiser acessar outros certificados (CA ou root, por exemplo) em outras áreas (específicos do usuário, por exemplo) veja a documentação do Open para saber que valores passar.
A função Close do Store tem que ser chamada quando não for mais usar o Store ou se for necessário reabrí-lo para acessar outro conjunto de certificados.

23 de abril de 2009

Trabalhando com o Certificate Store em Win32

Há alguns dias, postei um texto mostrando como acessar o Certificate Store do Windows através framework .NET e C#. Como nem todo mundo trabalha com .NET - a ABC71 mesmo usa o C++ Builder, que é Win32 - me perguntaram se é possível trabalhar no Win32 com aquelas classes do exemplo. A reposta curta é sim !
A resposta mais comprida é que isso envolve o uso de um ActiveX distribuído pela Microsoft chamado CAPICOM - Cryptographic Application Programming Interface através de COM.

Portanto, é necessário primeiro importar esse ActiveX, isto é, fazer com que o Delphi ou o C++ Builder gerem um arquivo fonte que nos permita utilizar as classes do CAPICOM. No passo a passo :
  1. Faça o download do CAPICOM e instale-o, caso ainda não o tenha feito.
  2. Localize a biblioteca capicom.dll e execute na linha de comando a seguinte instrução :

    regsvr32 capicom.dll

    Isto registra no Windows a Type Library associada a esse ActiveX.
  3. No Delphi : acesse, dentro do menu Component, a opção Import Component. Obs: Tenho a versão 2007 do Delphi mas não deve ser muito diferente nas outras. No C++ Builder 5, a opção de menu é Import Type Library, dentro do menu Project.
  4. Na janela que aparece, selecione Import a Type Library e pressione Next.
  5. Encontre o CAPICOM Type Libray na lista exibida e pressione Next.
  6. Nessa última tela, apenas marque a opção Generate Component Wrappers pois ele gera um código mais fácil de ser usado no C++ Builder.
  7. Pressione Finish e você tem um fonte com o mapeamento das classes do CAPICOM - inclusive aquelas que mostrei usando C#. Adicione esse fonte aos seus projetos que farão uso do CAPICOM.
Essas classes podem então ser usadas para acessar o Certificate Store e também para assinar documentos, criptografar e descriptografar informações, etc.

A Microsoft, no entanto, considera esse ActiveX obsoleto e recomenda que se use as classes conforme publicado no framework .NET. Além disso, a biblioteca ActiveX tem que ser distribuída e instalada junto com sua aplicação pois pode não estar presente em algumas máquinas.
Em todo caso, inclui alguns posts mostrando como usar as classes do CAPICOM no Delphi.