Validate XML signature
I Have a problem with a Signature validator to XML file, when this file have more than one Signature tag.
Like This
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<NFe>
<infNFe Id="NFexxx" versao="4.00">
...
</infNFe>
<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" />
<Reference URI="#NFexxx">
...
</Reference>
</SignedInfo>
...
</Signature>
</NFe>
<protNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<infProt Id="ID666">
...
</infProt>
<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" />
<Reference URI="#ID666">
...
</Reference>
</SignedInfo>
...
</Signature>
</protNFe>
</nfeProc>
<NFe>
<infNFe Id="NFexxx" versao="4.00">
...
</infNFe>
<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" />
<Reference URI="#NFexxx">
...
</Reference>
</SignedInfo>
...
</Signature>
</NFe>
<protNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<infProt Id="ID666">
...
</infProt>
<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" />
<Reference URI="#ID666">
...
</Reference>
</SignedInfo>
...
</Signature>
</protNFe>
</nfeProc>
This is my method of validation
Validate(file,element,clazz) ;new reader,sc,data,xmlSignature;set sc=reader.OpenFile(file)quit:$$$ISERR(sc) sc; get elementetdo reader.Correlate(element,clazz)if 'reader.Next(.data,.sc){quit sc };do reader.Correlate("Signature","%XML.Security.Signature")if 'reader.Next(.xmlSignature,.sc) {
quit sc};quit xmlSignature.ValidateDocument(data)I Get this error when to try call Validate("file.xml","NFe","class")
<METHOD DOES NOT EXIST>zValidateElement+35^%XML.Security.Signature.1 *GetNode "class"
Discussion (3)0
Comments
Try it like this:
new reader,sc,data,xmlSignature
set sc=reader.OpenFile(file)
quit:$$$ISERR(sc) sc
set document = reader.Document
do reader.Correlate("Signature","%XML.Security.Signature")
if 'reader.Next(.xmlSignature,.sc) {
quit sc
}
quit xmlSignature.ValidateDocument(document)
I talked to intersystems support. he asked me to break validation into two steps. one for each Tag. I'm trying to follow the support tips. But without success so far. In this example I'm trying to validate just the first <NFe> tag
; ; set sc=$$ValidateNFe("teste.xml","v400");ValidateNFe(cswFileNameOrStream,cswNFeVersion) ;new reader,sc,data,nfeStream,protNFeStream,clazzProc,clazzNFe,clazzProtNFe;set sc=$$Reader(cswFileNameOrStream,.reader)quit:$$$ISERR(sc) sc;set clazzProc="br.com.sefaz.nfe."_cswNFeVersion_".TNfeProc";set sc=##class(%Dictionary.CompiledClass).%ExistsId(clazzProc)quit:$$$ISERR(sc) $$$ERROR(10000,"Classe ("_clazzProc_") não existente!"); do reader.Correlate("nfeProc",clazzProc)if 'reader.Next(.data,.sc){quit $$$ERROR(10000,"Arquivo XML inválido!") };set sc=$$XmlToStream(data.NFe,.nfeStream)quit:$$$ISERR(sc) sc;set sc=##class(%XML.Document).GetDocumentFromStream(nfeStream,.document)do document.AddIDs()quit data.NFe.Signature.ValidateDocument(document)Reader(cswFileNameOrStream,cswReader) ;new sc;set cswReader=##class(%XML.Reader).%New()set sc=cswReader.OpenStream(cswFileNameOrStream)quit sc
XmlToStream(cswObj,xmlStream) ;new writer,sc;set writer=##class(%XML.Writer).%New() set writer.Charset="UTF-8"set writer.Indent=1set writer.NoXMLDeclaration=1set xmlStream=##class(%GlobalBinaryStream).%New();set sc=writer.OutputToStream(.xmlStream)quit:$$$ISERR(sc) sc;set sc=writer.RootObject(cswObj)quit sc I get this error
w sc FailedCheck
I believe that my "XmlToStream" rule is changing the original XML and therefore the validation was compromised. Does that make any sense?
HI all.....
I found a simple solution....
ValidateSignature(cswFileNameOrStream) ;new sc,status,xmlSignature,cswRootCA,reader;set cswRootCA="/certfiles/root_ca_icp-brasil.crt"set reader=##class(%XML.Reader).%New();set sc=reader.OpenFile(cswFileNameOrStream)quit:$$$ISERR(sc) sc;do reader.Correlate("Signature", "%XML.Security.Signature")while (reader.Next(.xmlSignature, .status) && (sc=$$$OK)) {set sc = xmlSignature.ValidateDocument(reader.Document,,cswRootCA)};quit sc