GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

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

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.

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…

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

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…

[code]/*

  • 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 onvaid@hotmail.com
    */
    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;
    

    }
    }
    [/code]

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;

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?

[quote=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?[/quote]

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

se quizer me encaminhe o seu codigo para analise…

onvaid.marques@gmail.com

É 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?

[quote=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?[/quote]

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…

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.

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??

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

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.

Ola, pessoal passando para agradecer a todos, e caso alguém ainda precise de ajuda estou a disposição… no email… onvaid.marques@gmail.com

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 é backupmensal@multiconecta.com.br.

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

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

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.

onv.hudson.marques@gmail.com