[RESOLVIDO] Como Selecionar o Certificado Digital Token e Assinar Arquivos no Formato PKCS7?

16 respostas
S

Ola,

Galera estou tentando desenvolver um assinador e verificador de arquivos digitais no formato pkcs7, já consigo de certa forma selecionar o certificado/listar, porem não tenho ideia de como dar continuidade para assinar um arquivo e verificar, bom eu já possuo a solução feita em DELPHI utilizando a CAPICOM.dll e a partir dai eu fiz uma dll que me possibilita utilizar no java ate ai eu fiz e esta funcionando, porem gostaria e preciso ter a solução toda em java, estou quebrando a cabeça heheh cedo ou tarde sai a solução toda ajuda é bem vinda e quem precisa de mim estamos ai…

Abraço e obrigado.

16 Respostas

S

Pessoal…

Já estou conseguindo selecionar o certificado digital pelo token e smart card…tranquilo…ta ficando show de bola…

mais ainda estou tendo problemas para assinar…quem poder me ajudar serei muito grato… INte mais…

M

se pudesse postar a resolução do problema para os usuários que tiverem a mesma dúvida, afinal a união faz a força

S

Pessoal ta ai a classe que eu desenvolvi---- quem quiser melhor ...favor postar depois pra galera vamos contribuir ...
Bom eu padronizei a classe a baixo como o utilizado no delphi...pois estou iniciando em java mais quero manter o maximo o padrão....

viva a liberdade....

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jvCert;

import java.security.*;
import java.security.Certificate;
import java.security.cert.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.*;
import java.util.logging.Logger;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

/**
 *
 * @author [email removido]
 */
public class OnCert {

    //Procedimento que retorna o Keystore
    public static KeyStore funcKeyStore(String strAliasTokenCert) throws NoSuchProviderException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException {

        String strResult = "";
        KeyStore ks = null;

        try {
            ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
            ks.load(null, null);

            Enumeration<String> aliasEnum = ks.aliases();

            while (aliasEnum.hasMoreElements()) {
                String aliasKey = (String) aliasEnum.nextElement();

                if (ks.isKeyEntry(aliasKey)) {
                    strResult = aliasKey;
                }

                if (ks.getCertificateAlias(ks.getCertificate(strResult)) == strAliasTokenCert) {
                    break;
                }
            }

        } catch (KeyStoreException ex) {
            System.out.println("ERROR " + ex.getMessage());
        }

        return ks;

    }

    //Procedimento de listagem dos certificados digitais
    public static String[] funcListaCertificados(boolean booCertValido) throws NoSuchProviderException, IOException, NoSuchAlgorithmException, CertificateException {

        //Estou setando a variavel para 20 dispositivos no maximo
        String strResult[] = new String[20];
        Integer intCnt = 0;

        try {
            KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
            ks.load(null, null);

            Enumeration<String> aliasEnum = ks.aliases();

            while (aliasEnum.hasMoreElements()) {
                String aliasKey = (String) aliasEnum.nextElement();

                if (booCertValido == false) {
                    strResult[intCnt] = aliasKey;
                } else if (ks.isKeyEntry(aliasKey)) {
                    strResult[intCnt] = aliasKey;
                }

                if (strResult[intCnt] != null) {
                    intCnt = intCnt + 1;

                }

            }

        } catch (KeyStoreException ex) {
            System.out.println("ERROR " + ex.getMessage());
        }

        return strResult;

    }

    //Procedimento que retorna a chave privada de um certificado Digital
    public static PrivateKey funcChavePrivada(String strAliasTokenCert, String strAliasCertificado, String strArquivoCertificado, String strSenhaCertificado) throws Exception {

        KeyStore ks = null;
        PrivateKey privateKey = null;

        if (strAliasTokenCert == null || strAliasTokenCert == "") {

            ks = KeyStore.getInstance("PKCS12");
            FileInputStream fis = new FileInputStream(strArquivoCertificado);
            //Efetua o load do keystore
            ks.load(fis, strSenhaCertificado.toCharArray());
            //captura a chave privada para a assinatura
            privateKey = (PrivateKey) ks.getKey(strAliasCertificado, strSenhaCertificado.toCharArray());

        } else {

            if (strSenhaCertificado == null || strSenhaCertificado == "") {
                strSenhaCertificado = "Senha";
            }

            //Procedimento para a captura da chave privada do token/cert
            privateKey = (PrivateKey) funcKeyStore(strAliasTokenCert).getKey(strAliasTokenCert, strSenhaCertificado.toCharArray());

        }

        return privateKey;

    }

    //Procedimento que retorna a chave publica de um certificado Digital
    public static PublicKey funcChavePublica(String strAliasTokenCert, String strAliasCertificado, String strArquivoCertificado, String strSenhaCertificado) throws Exception {

        KeyStore ks = null;
        PublicKey chavePublica = null;

        if (strAliasTokenCert == null || strAliasTokenCert == "") {

            ks = KeyStore.getInstance("PKCS12");
            FileInputStream fis = new FileInputStream(strArquivoCertificado);

            //InputStream entrada para o arquivo
            ks.load(fis, strSenhaCertificado.toCharArray());
            fis.close();
            Key chave = (Key) ks.getKey(strAliasCertificado, strSenhaCertificado.toCharArray());
            //O tipo de dado é declarado desse modo por haver ambigüidade (Classes assinadas com o mesmo nome "Certificate")
            java.security.Certificate cert = (java.security.Certificate) ks.getCertificate(strAliasCertificado);
            chavePublica = cert.getPublicKey();

        } else {

            if (strSenhaCertificado == null || strSenhaCertificado == "") {
                strSenhaCertificado = "Senha";
            }

            //Procedimento se for utilizar token para a captura de chave publica
            ks = funcKeyStore(strAliasTokenCert);
            Key key = ks.getKey(strAliasTokenCert, strSenhaCertificado.toCharArray());
            java.security.cert.Certificate crtCert = ks.getCertificate(strAliasTokenCert);
            chavePublica = crtCert.getPublicKey();

        }

        return chavePublica;

    }

    //Procedimento que verifica a assinatura
    public static boolean funcAssinaturaValida(PublicKey pbKey, byte[] bteBuffer, byte[] bteAssinado, String strAlgorithmAssinatura) throws Exception {

        if (strAlgorithmAssinatura == null) {
            strAlgorithmAssinatura = "MD5withRSA";
        }

        Signature isdAssinatura = Signature.getInstance(strAlgorithmAssinatura);
        isdAssinatura.initVerify(pbKey);
        isdAssinatura.update(bteBuffer, 0, bteBuffer.length);
        return isdAssinatura.verify(bteAssinado);

    }

    //Procedimento que gera a assinatura
    public static byte[] funcGeraAssinatura(PrivateKey pbKey, byte[] bteBuffer, String strAlgorithmAssinatura) throws Exception {

        if (strAlgorithmAssinatura == null) {
            strAlgorithmAssinatura = "MD5withRSA";
        }

        Signature isdAssinatura = Signature.getInstance(strAlgorithmAssinatura);
        isdAssinatura.initSign(pbKey);
        isdAssinatura.update(bteBuffer, 0, bteBuffer.length);
        return isdAssinatura.sign();

    }

    //Procedimento que retorna o status do certificado
    public static String funcStatusCertificado(X509Certificate crtCertificado) {

        try {
            crtCertificado.checkValidity();
            return "Certificado válido!";
        } catch (CertificateExpiredException E) {
            return "Certificado expirado!";
        } catch (CertificateNotYetValidException E) {
            return "Certificado inválido!";
        }

    }

    //Procedimento que retorna o certificado selecionado
    public static X509Certificate funcCertificadoSelecionado(String strAliasTokenCert, String strAliasCertificado, String strArquivoCertificado, String strSenhaCertificado) throws NoSuchProviderException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException, KeyStoreException {

        X509Certificate crtCertificado = null;
        KeyStore crtRepositorio = null;

        if (strAliasTokenCert == null || strAliasTokenCert == "") {

            //Procedimento de captura do certificao arquivo passado como parametro
            InputStream dado = new FileInputStream(strArquivoCertificado);
            crtRepositorio = KeyStore.getInstance("PKCS12");
            crtRepositorio.load(dado, strSenhaCertificado.toCharArray());
            crtCertificado = (X509Certificate) crtRepositorio.getCertificate(strAliasCertificado);

        } else {

            if (strSenhaCertificado == null || strSenhaCertificado == "") {
                strSenhaCertificado = "Senha";
            }

            //Procedimento de captura do certificao token passado como parametro
            KeyStore.PrivateKeyEntry keyEntry;
            try {
                keyEntry = (KeyStore.PrivateKeyEntry) funcKeyStore(strAliasTokenCert).getEntry(strAliasTokenCert, new KeyStore.PasswordProtection(strSenhaCertificado.toCharArray()));

                crtCertificado = (X509Certificate) keyEntry.getCertificate();
            } catch (KeyStoreException ex) {
                Logger.getLogger(CertEL.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        return crtCertificado;

    }

    //Procedimento de Parametros de assinatura
    public static class TAssinaXML {

        //MD2withRSA - MD5withRSA - SHA1withRSA - SHA224withRSA - SHA256withRSA - SHA1withDSA - DSA - RawDSA
        //public String strAlgorithmAssinatura = "MD5withRSA";
        public String strAliasTokenCert = null;
        public String strAliasCertificado = null;
        public String strArquivoCertificado = null;
        public String strSenhaCertificado = null;
        public String strArquivoXML = null;
        public String strArquivoSaveXML = null;
        public String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
        public boolean booNFS = true;
    }

    //Procedimento de assinar XML
    public static boolean funcAssinaXML(TAssinaXML tpAssinaXML) throws Exception {

        Signature sgi = null;
        
        XMLSignatureFactory sig = null;
        SignedInfo si = null;
        KeyInfo ki = null;
        String strTipoSign = "infNFe";
        String strID = "Id";

        if (tpAssinaXML.booNFS) {
            strTipoSign = "LoteRps";//"InfNfse";
            strID = "Id";
        }

        //Capturo o certificado
        X509Certificate cert = funcCertificadoSelecionado(tpAssinaXML.strAliasTokenCert, tpAssinaXML.strAliasCertificado, tpAssinaXML.strArquivoCertificado, tpAssinaXML.strSenhaCertificado);

        //Inicializo o arquivo/carrego
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(tpAssinaXML.strArquivoXML));

        sig = XMLSignatureFactory.getInstance("DOM");


        ArrayList<Transform> transformList = new ArrayList<Transform>();
        Transform enveloped = sig.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
        Transform c14n = sig.newTransform(tpAssinaXML.C14N_TRANSFORM_METHOD, (TransformParameterSpec) null);
        transformList.add(enveloped);
        transformList.add(c14n);

        NodeList elements = doc.getElementsByTagName(strTipoSign);
        org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(0);

        String id = el.getAttribute(strID);

        Reference r = sig.newReference("#".concat(id), sig.newDigestMethod(DigestMethod.SHA1, null),
                transformList,
                null, null);
        si = sig.newSignedInfo(
                sig.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                (C14NMethodParameterSpec) null),
                sig.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                Collections.singletonList(r));

        KeyInfoFactory kif = sig.getKeyInfoFactory();
        List x509Content = new ArrayList();
        x509Content.add(cert);
        X509Data xd = kif.newX509Data(x509Content);
        ki = kif.newKeyInfo(Collections.singletonList(xd));

        DOMSignContext dsc = new DOMSignContext(funcChavePrivada(tpAssinaXML.strAliasTokenCert, tpAssinaXML.strAliasCertificado, tpAssinaXML.strArquivoCertificado, tpAssinaXML.strSenhaCertificado), doc.getDocumentElement());
        XMLSignature signature = sig.newXMLSignature(si, ki);

        signature.sign(dsc);

        //Salvo o arquivo assinado
        OutputStream os = new FileOutputStream(tpAssinaXML.strArquivoSaveXML);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));

        return true;

    }
}

E para efetuar o uso vai como exemplo abaixo simples obvio hehehehe
Esse abaixo é o de efetua a listagem de certificado

OnCert Cert = new OnCert ();

        int intCnt = 0;
        String[] strCertAlias = null;
        strCertAlias = Cert.funcListaCertificados(false);

        while (strCertAlias[intCnt] != null) {
            cbxSelecionaCert.add(strCertAlias[intCnt]);
            intCnt = intCnt + 1;
        }

E esse aqui é para executar a assinatura uma das formas heheh;

try {
            OnCert Cert = new OnCert();
            OnCert.TAssinaXML tpAssinaXML = new OnCert.TAssinaXML();
            tpAssinaXML.strAliasTokenCert = cbxSelecionaCert.getSelectedItem();
            tpAssinaXML.strArquivoXML = "D:\\lote_rps_envio.xml";
            tpAssinaXML.strArquivoSaveXML = "D:\\XMLsigned.xml";
            Cert.funcAssinaXML(tpAssinaXML);
        } catch (Exception e) {
            e.printStackTrace();
        }

viva a liberdade viva....o java;

D

Não sei se já aconteceu com vocês, mas eu executo o código acima para carregar os certificados e funciona na primeira vez, na segunda não mais… Eu tenho que tirar o token e colocar novamente para voltar a funcionar…

Alguém sabe o que pode ser isso?

S

DexterDF:
Não sei se já aconteceu com vocês, mas eu executo o código acima para carregar os certificados e funciona na primeira vez, na segunda não mais… Eu tenho que tirar o token e colocar novamente para voltar a funcionar…

Alguém sabe o que pode ser isso?

Fera…nao estou tendo nenhum problema em relacao a isso…!!!

se quizer me encaminhe o seu codigo para analise…

[email removido]

D

É exatamente o mesmo… estou achando que pode ser algum conflito do Windows 7 e o Java… É como se ele travasse o Token na chamada anterior…
Eu fiz o teste em outro computador e o problema é o mesmo… Mudei os tokens e o problema continua…

Muito estranho, alguém já ouviu falar?

S

DexterDF:
É exatamente o mesmo… estou achando que pode ser algum conflito do Windows 7 e o Java… É como se ele travasse o Token na chamada anterior…
Eu fiz o teste em outro computador e o problema é o mesmo… Mudei os tokens e o problema continua…

Muito estranho, alguém já ouviu falar?

Rapaz muito estranho mesmo…heheheh eu fiz este algoritimo no windows 7 e nao to tendo nenhum problema…to testando aqui no mesmo …e ta funcionando corretamente…
nao sei o que pode estar ocorrendo ai com vc…

samuk1

Bom Dia… Gostei muito Do Que vc me passou ai, está carregando os certificados beleza! Muito Obrigado Por este Codigo!

Mas ele tem 3 Metodos:

-funcChavePrivada // Que pega a chave Publica
-funcChavePublica // Que pega a chave Privada
-funcCertificadoSelecionado // Que pega o Certificado (X509)

Qual Deles eu Devo Carregar para jogar nesta Variavel?

System.setProperty("javax.net.ssl.keyStore", caminhoDoCertificadoDoCliente);

2ª Duvida

Em todos essses metodos , Precisam ser passados os Seguintes Parametro:

String strAliasTokenCert, String strAliasCertificado, String strArquivoCertificado, String strSenhaCertificado

Onde:

strAliasTokenCert : É o Alias que eu vejo quando mando Listar os Certificados
strAliasCertificado : Não Sei que Alias é esse.
strArquivoCertificado : Acredito que seja um caminho Do Certificado, mas pq?
strSenhaCertificado : Senha certificado

Então , Quais Parametro passo para “strAliasCertificado” , “strArquivoCertificado”…

Abraços.

esqueleto

Para funcionar tem q estar o smart card conectado ao pc??
Só a instalação do certificado através do driver q vem junto com o cd já é o suficiente e depois posso remover e continua reconhecendo o certificado?
Os certificados listados são apenas os de origem de smart card??

T

Consegui Assinar mas nao to conseguindo enviar ela alguem me ajuda =/

josemdvdf

Pessoal, já consegui fazer a leitura do Token a3 e assinar um arquivo. Mas estou com o seguinte problema: o sistema que estou trabalhando gera um certificado que pode ser usado somente nele. No entanto quando o usuário instala o certificado e digita a senha, ela nunca mais é solicitada no mesmo computador.

Alguém sabe dizer se isso é configurável no navegador ou se isso é alguma configuração de leitura ? existe a possibilidade de sempre forçar o usuário a digitar a senha ?

Obrigado.

S

Ola, pessoal passando para agradecer a todos, e caso alguém ainda precise de ajuda estou a disposição… no email… [email removido]

A URL solicitada não pôde ser recuperada
Na tentativa de recuperar a URL:
http://www.guj.com.br/jforum.java
O seguinte erro foi encontrado:
Resposta com tamanho zero

O squid não recebeu nenhum dado para esse pedido.

O administrador do cache é [email removido].

E

boa tarde pessoal quero pedir ajuda, eu programo em delphi e como li que vc Soulslinux tem a rotina em delphi poderia me passar to desesperado pra assinar xml mas nem sei como fazer se puder me ajudar fico agradecido, abraços

M

Estou com problema para realizar a assinatura com DELPHI, teria como disponibilizar a solução aqui no forum. A minha abaixo da erro na linha XmlAssinada := AssinaturaXML.sign(XmlAssina,NOKEYINFO);

procedure TFormImportaXMLNFe.TestaAssinaturaCapicom(Sender: TObject);

const

xml: string = <?xml version="1.0" encoding="UTF-8" ?>+

’’ +

‘71’ +

’’ +

’’ +

‘35’ +

‘518005127’ +

Venda a vista +

‘55’ +

‘1’ +

‘2012-05-06’ +

‘2’ +

’’ +

’’ +

’’;
var

Store: IStore3;

CertsLista, CertsSelecionado: ICertificates2;

CertDados: ICertificate;

Cert: ICertificate2;

lSigner: TSigner;

lSignedData: TSignedData;

arquivoxml : TStringList;

tipo : string;

filenameIn, filenameOut : string;
PosId, PosSignature: Integer;

UriNfe: string;

NfeAssinada: AnsiString;

DocumentDOM : IXMLDOMDocument3;

AssinaturaXML: IXMLDigitalSignature;

XmlAssina, XmlAssinada: IXMLDSigKey;

ChaverPrivada: IPrivateKey;

StrStream : TStringStream;

begin

inherited;

filenameIn := ClaPath.TempPath + ‘teste_ENVIO.xml’;
filenameOut:= ClaPath.TempPath + ‘teste_assinada.xml’;

arquivoxml := TStringList.Create;
arquivoxml.Clear;

Store := CoStore.Create;

try

Store.Open(CAPICOM_CURRENT_USER_STORE, My, CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

except

On E: Exception do

begin

MsgErro(E.Message);

Exit;

end;

end;
try

CertsLista := Store.Certificates as ICertificates2;

CertsSelecionado := CertsLista.Select

(Certificado(s) Digital(is) disponível(is),

Selecione o Certificado Digital para uso no aplicativo, False);

except

On E: Exception do

begin

MsgAvisa(Operação cancelada pelo usuário!);

Exit;

end;

end;

if not(CertsSelecionado.Count = 0) then
begin
CertDados := IInterface(CertsSelecionado.Item[1]) as ICertificate2;

lSigner := TSigner.Create(nil);
lSigner.Certificate := CertDados;

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

try
  lSignedData.Sign(lSigner.DefaultInterface, false, CAPICOM_ENCODE_BINARY);
except
  On E : Exception do
    MsgErro('Erro na autenticação do Certificado Digital!' + e.Message);
end;

Cert := IInterface(CertsSelecionado.Item[1]) as ICertificate2;
if (Now >= Cert.ValidFromDate) and (Cert.ValidToDate >= Now) then
begin
  Tipo := 'NFe';
  if pos('<inf' + Tipo, xml)>0 then
  begin
    PosId := Pos('id=', xml);
    UriNfe := copy(xml, PosId + 4, 47);
    ArquivoXml.Add(Copy(xml, 1, pos('</'+ Tipo +'>', xml)-1));
    ArquivoXml.Add('<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'+
                               '<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>'+
                               '<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />');
    ArquivoXML.Add('<Reference URI="#'+ UriNFe +'"><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" />');
    ArquivoXML.Add('<DigestValue></DigestValue></Reference></SignedInfo>'+
                                '<SignatureValue></SignatureValue><KeyInfo></KeyInfo></Signature>');

    ArquivoXML.Add('</'+ Tipo +'>');
    ArquivoXML.Add('</enviNFe>');
  end;

  DocumentDOM := CoDOMDocument50.Create;
  with DocumentDOM do
  begin
    async := false;
    validateOnParse := False;
    preserveWhiteSpace :=true;
    loadXML(ArquivoXml.GetText);
    setProperty('SelectionNamespaces', 'xmlns:ds="http://www.w3.org/2000/09/xmldsig#"');
    save(filenameIn);
  end;

  try
    AssinaturaXML := CoMXDigitalSignature50.Create;
    AssinaturaXML.signature:= DocumentDOM.selectSingleNode('.//ds:Signature');
    AssinaturaXML.store := Store;
    try
      OleCheck(IDispatch(cert.PrivateKey).QueryInterface(iprivatekey, ChaverPrivada));
    except
      on e: Exception do
      begin
        MsgErro(e.Message);
      end;
    end;

    try
      XmlAssina   := AssinaturaXML.createKeyFromCSP(ChaverPrivada.ProviderType, ChaverPrivada.ProviderName, ChaverPrivada.ContainerName, 0);
    except
      on e: Exception do
      begin
        MsgErro(e.Message);
      end;
    end;

    try
      XmlAssinada := AssinaturaXML.sign(XmlAssina,NOKEYINFO);
    except
      on e: Exception do
      begin
        MsgErro(e.Message);
      end;
    end;

    NfeAssinada := AnsiString(DocumentDOM.xml);
    NfeAssinada := AnsiString(StringReplace(String(NfeAssinada), chr(13), '' ,[rfReplaceall]));
    NfeAssinada := AnsiString(StringReplace(String(NfeAssinada), chr(10), '' ,[rfReplaceall]));
    PosSignature := pos('<SignatureValue>', String(NfeAssinada)) +16;
    NfeAssinada :=AnsiString(copy(String(NfeAssinada), 1, PosSignature) + StringReplace(copy(String(NfeAssinada), posSignature, length(String(NfeAssinada))),'' ,'', [rfReplaceall])) ;
    StrStream := TStringStream.Create();
    StrStream.WriteString(String(NfeAssinada));
    StrStream.SaveToFile(filenameOut);
  except
    on E: Exception do
    begin
      MsgErro(e.Message);
    end;
  end;
  XmlAssinada :=nil;
  XmlAssina := nil;
  AssinaturaXML:=nil;
  DocumentDOM := nil;
end;
end;

Store.Close;

end;

Alguem sabe como solucionar. Versão delphi Tokio

S

Marcos, não consigo lhe ajudar neste exato momento, pois estou sem o Delphi, vou localizar a minha maquina virtual e assim que eu conseguir eu volto a falar com você, a solução em Delphi atualmente eu estou vendendo a solução completa, mas como o seu código está quase finalizado vou te da uma mão para finalizar ele.

[email removido]

A

Olá boa noite @Soulslinux tudo bem? Estou começando a fazer um projeto para selecionar o certificado digital e salvar no banco de dados com criptografia, eu vi que colocou algumas classes sobre isto, será que poderia compartilhar o projeto comigo?

Caso sim, tenho gmail também é [email removido]

Desde já agradeço pela atenção e pela ajuda!!!

Criado 4 de julho de 2010
Ultima resposta 18 de fev. de 2021
Respostas 16
Participantes 10