[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…

S

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.

E

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 =/

J

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