This page explains the logic behind the FirmaSAT On-line Validator and shows the function calls from the FirmaSAT library.
Input XML file (Combrobante archivo XML): fname = "Prueba2Notario_iedu-tfd.xml"
PAC X.509 Certificate (Certificado del SAT): certname = "pac.cer"
Each step of the procedure is described below. A simplified copy of the original C/C++ code is given together with the relevant C# code statements and the closest command-line instruction.
long receiptver = SAT_XmlReceiptVersion(fname, 0);Code in C# is shown in the form
int receiptver = Sat.XmlReceiptVersion(fname);The closest command-line instruction is shown in the form
FirmaSAT RECEIPTVERSION fname.xml
VB6/VBA programmers should be able to figure out their equivalent code from the C code. Similarly, VB.NET and Java programmers should be able to derive their code from the C# code. The command-line instructions should at least give an idea as to how to derive the required information.
Reference: Get XML Receipt Version Number
long receiptver = SAT_XmlReceiptVersion(fname, 0);
switch (receiptver) {
case 2:
recverstr = "2.0";
doctype = "CFD";
is_cfdi = 0;
break;
case 3:
recverstr = "3.0";
doctype = "CFDI";
is_cfdi = 1;
break;
case 22:
recverstr = "2.2";
doctype = "CFD";
is_cfdi = 0;
break;
case 32:
recverstr = "3.2";
doctype = "CFDI";
is_cfdi = 1;
break;
default:
ERROR();
break;
}
printf("%s standard version: %s\n", doctype, recverstr);
int receiptver = Sat.XmlReceiptVersion(fname);
FirmaSAT RECEIPTVERSION fname.xml
References: Validate XML Document, Error-related procedures
r = SAT_ValidateXml(fname, 0); if (0 == r) { printf("XML structure is valid\n"); } else { printf("XML structure is NOT valid\n"); SAT_LastError(errbuf, SAT_MAX_ERROR_CHARS); printf("%s\n", errbuf); // But only quit if it does not pass the "loose" test r = SAT_ValidateXml(fname, SAT_XML_LOOSE); if (r != 0) ERROR(); }
r = Sat.ValidateXml(fname); errbuf = General.LastError(); r = Sat.ValidateXml(fname, XmlOption.Loose);
FirmaSAT XMLOK fname.xml FirmaSAT XMLOK -l fname.xml
Reference: Make Pipe String
nchars = SAT_MakePipeStringFromXml(NULL, 0, fname, 0); if (nchars < 0) ERROR(); pipebuf = MALLOC(nchars+1); nchars = SAT_MakePipeStringFromXml(pipebuf, nchars, fname, 0);
string pipebuf = Sat.MakePipeStringFromXml(fname);
if (pipebuf.Length == 0) ERROR();
FirmaSAT PIPESTRING fname.xml
Reference: Make Digest
char digest[SAT_MAX_HASH_CHARS+1] = { 0 };
r = SAT_MakeDigestFromXml(digest, sizeof(digest)-1, fname, 0);
printf("%s\n", digest);
string digest = Sat.MakeDigestFromXml(fname);
Console.WriteLine("{0}", digest);
FirmaSAT FORMDIGEST fname.xml
References: Query a Certificate, Get XML Attribute
char certused[32] = { 0 }; char certrept[32] = { 0 }; r = SAT_QueryCert(certused, sizeof(certused)-1, fname, "serialNumber", 0); printf("Certificate used: %s\n, certused); r = SAT_GetXmlAttribute(certrept, sizeof(certrept)-1, fname, "noCertificado", "Comprobante"); printf("Certificate reported: %s\n, certrept);
string certused = Sat.QueryCert(fname, Query.serialNumber); Console.WriteLine("Certificate used: {0}", certused); string certrept = Sat.GetXmlAttribute(fname, "noCertificado", "Comprobante"); Console.WriteLine("Certificate reported: {0}", certrept);
FirmaSAT QUERYCERT -q serialNumber fname.xml FirmaSAT ATTRIBUTE -a noCertificado -e Comprobante fname.xml
Reference: Verify XML Signature
r = SAT_VerifySignature(fname, NULL, 0);
if (0 == r) {
printf("The %s signature is valid\n", doctype);
} else {
printf("The %s signature is NOT valid\n", doctype);
ERROR();
}
r = Sat.VerifySignature(fname);
FirmaSAT VERIFYSIG fname.xml
if (is_cfdi) { // See step 1 long r = SAT_GetXmlAttribute(NULL, 0, fname, "selloCFD", "tfd:TimbreFiscalDigital"); if (r < 0) ERROR("the TFD signature is missing"); }
string s = Sat.GetXmlAttribute(fname, "selloCFD", "tfd:TimbreFiscalDigital");
if (s.Length == 0) ERROR("the TFD signature is missing");
FirmaSAT ATTRIBUTE -a selloCFD -e tfd:TimbreFiscalDigital fname.xml
Reference: Timbre Fiscal Digital (TFD) element
nchars = SAT_MakePipeStringFromXml(NULL, 0, fname, SAT_TFD); if (nchars < 0) ERROR(); pipebuf = MALLOC(nchars+1); nchars = SAT_MakePipeStringFromXml(pipebuf, nchars, fname, SAT_TFD);
string pipebuf = Tfd.MakePipeStringFromXml(fname);
if (pipebuf.Length == 0) ERROR();
FirmaSAT PIPESTRING -f fname.xml
char digest[SAT_MAX_HASH_CHARS+1] = { 0 };
r = SAT_MakeDigestFromXml(digest, sizeof(digest)-1, fname, SAT_TFD);
printf("%s\n", digest);
string digest = Tfd.MakeDigestFromXml(fname);
Console.WriteLine("{0}", digest);
FirmaSAT FORMDIGEST -f fname.xml
char certused[32] = { 0 }; char certrept[32] = { 0 }; r = SAT_QueryCert(certused, sizeof(certused)-1, certname, "serialNumber", 0); printf("Certificate used: %s\n, certused); r = SAT_GetXmlAttribute(certrept, sizeof(certrept)-1, fname, "noCertificadoSAT", "tfd:TimbreFiscalDigital"); printf("Certificate reported: %s\n, certrept);
string certused = Sat.QueryCert(certname, Query.serialNumber); Console.WriteLine("Certificate used: {0}", certused); string certrept = Sat.GetXmlAttribute(fname, "noCertificadoSAT", "tfd:TimbreFiscalDigital"); Console.WriteLine("Certificate reported: {0}", certrept);
FirmaSAT QUERYCERT -q serialNumber certname.cer FirmaSAT ATTRIBUTE -a noCertificadoSAT -e tfd:TimbreFiscalDigital fname.xml
r = SAT_VerifySignature(fname, certname, SAT_TFD);
if (0 == r) {
printf("The TFD signature is valid\n");
} else {
printf("The TFD signature is NOT valid\n");
ERROR();
}
r = Tfd.VerifySignature(fname, certname);
FirmaSAT VERIFYSIG -f -c certname.cer fname.xml
printf("Produced using FirmaSAT v.%ld.", SAT_Version());
Console.WriteLine("Produced using FirmaSAT v.{0}", General.Version());
FirmaSAT LIBINFO
You can download a fully-functional trial version of FirmaSAT from here.
To comment on this page, make a suggestion for improvement, or for further information, please send us a message.
This page last updated 15 August 2025.