Assinatura documento xml com capicom e msxml5
procedure TFormImportaXMLNFe.TestaAssinaturaCapicom(Sender: TObject);
const
xml: string = '<?xml version="1.0" encoding="UTF-8" ?>'+
'<enviNFe versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">' +
'<idLote>71</idLote>' +
'<NFe>' +
'<infNFe id="NFe31120723401920000117550020000295121002311579" 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>';
var
Store: IStore3;
CertsLista, CertsSelecionado: ICertificates2;
CertDados: ICertificate;
Cert: ICertificate2;
lSigner: TSigner;
lSignedData: TSignedData;
tipo, arquivoxml : 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 := 'Z:\\Projetos\\Udilink NFe -2\\SRC\\NFE\\Assinador\\teste_ENVIO.xml';
filenameOut:= 'Z:\\Projetos\\Udilink NFe -2\\SRC\\NFE\\Assinador\\teste_assinada.xml';
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 := Copy(xml, 1, pos('</'+ Tipo +'>', xml)-1);
ArquivoXml := ArquivoXml + '<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 := ArquivoXML + '<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 := ArquivoXML + '<DigestValue></DigestValue></Reference></SignedInfo>'+
'<SignatureValue></SignatureValue><KeyInfo></KeyInfo></Signature>';
ArquivoXML := ArquivoXML + '</'+ Tipo +'>';
ArquivoXML := ArquivoXML + '</enviNFe>';
end;
DocumentDOM := CoDOMDocument50.Create;
with DocumentDOM do
begin
async := false;
validateOnParse := False;
preserveWhiteSpace :=true;
loadXML(ArquivoXml);
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
AssinaturaXML.verify(XmlAssina);
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;
Não consigo realizar o processo como um todo dá erro na linha XmlAssinada := AssinaturaXML.sign(XmlAssina,NOKEYINFO);
Alguem pode me ajudar
const
xml: string = '<?xml version="1.0" encoding="UTF-8" ?>'+
'<enviNFe versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">' +
'<idLote>71</idLote>' +
'<NFe>' +
'<infNFe id="NFe31120723401920000117550020000295121002311579" 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>';
var
Store: IStore3;
CertsLista, CertsSelecionado: ICertificates2;
CertDados: ICertificate;
Cert: ICertificate2;
lSigner: TSigner;
lSignedData: TSignedData;
tipo, arquivoxml : 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 := 'Z:\\Projetos\\Udilink NFe -2\\SRC\\NFE\\Assinador\\teste_ENVIO.xml';
filenameOut:= 'Z:\\Projetos\\Udilink NFe -2\\SRC\\NFE\\Assinador\\teste_assinada.xml';
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 := Copy(xml, 1, pos('</'+ Tipo +'>', xml)-1);
ArquivoXml := ArquivoXml + '<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 := ArquivoXML + '<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 := ArquivoXML + '<DigestValue></DigestValue></Reference></SignedInfo>'+
'<SignatureValue></SignatureValue><KeyInfo></KeyInfo></Signature>';
ArquivoXML := ArquivoXML + '</'+ Tipo +'>';
ArquivoXML := ArquivoXML + '</enviNFe>';
end;
DocumentDOM := CoDOMDocument50.Create;
with DocumentDOM do
begin
async := false;
validateOnParse := False;
preserveWhiteSpace :=true;
loadXML(ArquivoXml);
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
AssinaturaXML.verify(XmlAssina);
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;
Não consigo realizar o processo como um todo dá erro na linha XmlAssinada := AssinaturaXML.sign(XmlAssina,NOKEYINFO);
Alguem pode me ajudar
Marcos Barbosa
Curtidas 0