<!--
meta-author: David Ireland, DI Management Services Pty Limited, Australia, https://di-mgt.com.au
meta-content-style-type: text/css
meta-content-type: text/html; charset=UTF-8
meta-copyright: Copyright (C) 2010-25 DI Management Services Pty Limited, ABN 78 083 210 584 All Rights Reserved
meta-date: 2022-03-13T01:03Z
meta-description: FirmaSAT Manual
meta-viewport: width=device-width, initial-scale=1
title: FirmaSAT v10.70 Manual
-->

<a id="topofpage"></a>FirmaSAT Manual
=====================================

Contents
--------

* [Introduction](#introduction)
* [Key file format](#keyfileformat)
* **Signature creation and validation**

    + [Sign XML](#SignXML)
        + [Make Signature](#MakeSignature)
        + [Verify XML Signature](#VerifyXMLSignature)
* **XML Structure**

    + [Validate XML Document](#ValidateXMLDocument)
        + [Get XML Attribute](#GetXMLAttribute)
            - [Simplified XPath expressions for the elementName parameter](#xpathexpression)
        + [Asciify an XML document](#AsciifyXmlDocument)
        + [Get XML Receipt Version Number](#getxmlreceiptversion)
        + [Fix UTF-8 BOM](#fixutf8bom)
* **X.509 Certificate**

    + [Get Certificate as a String](#GetCertificateAsAString)
        + [Insert certificate details](#InsertCertificateDetails)
        + [Get Certificate Serial Number](#GetCertificateSerialNumber)
        + [Get Certificate Validity Dates](#GetCertificateValidityDates)
        + [Query a Certificate](#querycert)
* **Private Key**

    + [Get Private Key as a String](#GetPrivateKeyAsAString)
        + [Check Key and Certificate](#checkkeyandcert)
        + [Save key file with a new password](#SaveKeyFile)
        + [Make a PFX File](#writepfxfile)
* **Signature/Pipestring Analysis**

    + [Make Pipe String](#MakePipeString)
        + [Make Digest](#MakeDigest)
        + [Extract Digest From Signature](#ExtractDigestFromSignature)
* **Miscellaneous**

    + [Generate a UUID](#generateuuid)
        + [BIGFILE option](#bigfileoption)
        + [Notes on CFD v4.0 and v3.3](#notesoncfdv33)
* **Timbre Fiscal Digital (TFD)**

    + [Timbre Fiscal Digital (TFD) element](#tfdelement)
        + [Adding a TFD element](#addtfd)
* **Help and information**

    + [Diagnostic Procedures](#diagnosticprocs)
        + [Error-related procedures](#errorprocs)
        + [Error Codes](#errorcodes)
* **Programming and CLI**

    + Programming reference documentation
            - [ANSI C/C++](diFirmaSat2_h_Ref.html) - diFirmaSat2.h File Reference
                - [C++ (STL)](cppfsa/html/index.html) - The C++ (STL) interface to FirmaSAT
                - [VBA/VB6](basFirmaSAT.bas.manual.html) - basFirmaSAT.bas File Reference
                - [.NET (C# and `VB.NET`)](fsaDotNetManual.html) - FirmaSAT .NET Class Library
        + [Command-line utility](#commandlineutility)
            - [Example batch file](#batchfile)
        + [C/C++ Programming](#cplusplusprogramming)
            - [Pre-dimensioning szOut](#predimensioningszout)
        + [C++ (STL) Programming](#cppprogramming)
        + [VB6/VBA Programming](#vb6programming)
        + [`VB.NET`/VB2010+ programming](#vbnetprogramming)
        + [C# programming](#csharpprogramming)
* [Changes in this version](#changesinthis)

    + [Changes in older versions](#changesinolder)
* [Index](#index)
* [Revision History](#Revisions)

<a id="introduction"></a>Introduction
-------------------------------------

FirmaSAT 
is a stand-alone utility 
which enables you to create and read 
digital receipts (Comprobantes Fiscal Digital) 
as specified by the Tax Administration Service (Servicio de Administración Tributaria) (SAT) in Mexico.
It handles CFDi version 4.0 and 3.3 documents together with the latest supplements 
(Complementos de Factura Electrónica (CFDI)).

FirmaSAT also handles the following extra documents: 

* Retenciones version 1.0 and 2.0 documents
(Retenciones e información de pagos).
* Controles volumétricos version 1.1 and 1.2 documents
(del Archivo XML de Controles Volumétricos para Gasolina o Diesel).
* Contabilidad electrónica documents
(Contabilidad en medios electrónicos) versions 1.1 and 1.3.

    + CatalogoCuentas
        + BalanzaComprobacion
        + PolizasPeriodo
        + AuxiliarFolios
        + AuxiliarCtas
        + SelloDigitalContElec

The document type is automatically detected, and the correct hash algorithm (SHA-1 or SHA-256) for digests and signatures is automatically chosen depending on the document type.

FirmaSAT  is a self-contained stand-alone product which 
does not require *any* external libraries.
FirmaSAT does not use slow external XML libraries or unreliable cryptographic libraries.

This manual contains the syntax and examples for the [command-line utility](#commandlineutility) `FirmaSAT.exe`
and the programming interfaces to the core DLL library `diFirmaSAT2.dll` using the supported languages
[ANSI C/C++](#cplusplusprogramming),
[C++ (STL)](#cppprogramming),
[VB6/VBA](#vb6programming),
[`VB.NET`/VB2010+](#vbnetprogramming) and
[C#](#csharpprogramming).
Interfaces for 
[Python](python.html),
[Java](java.html)
and [Delphi/Free Pascal](https://cryptosys.net/delphi.html "External link")
are available separately from our web site.

Please note that in all cases it is up to the user to create and provide a well-formed XML file as input.

For instructions on how to install, using other programming languages, and more recent updates to this manual, please see our 
[FirmaSAT page](https://cryptosys.net/firmasat/ "External link").

The Spanish translations in this document are from [Google Translate](https://translate.google.com/ "External link"):
Mi aerodeslizador está lleno de anguilas!

<a id="notesoncfdv33"></a>Notes on CFD v4.0 and v3.3
----------------------------------------------------

These notes were written when v3.3 was introduced and superseded v3.2 in 2017. All these notes are equally valid for v4.0 (introduced 2021).

* The attribute names in v4.0/3.3 all begin with capital letters, so `sello` in v3.2 becomes `Sello` in v3.3.
Be careful to change the attribute argument in any calls to [GetXMLAttribute](#GetXMLAttribute).

    ```

    FirmaSAT ATTRIBUTE -d -a sello -e Comprobante -i cfdv33-signed-tfd.xml
    Attribute=[sello] Element=[Comprobante]
    Error code -21: Match not found/No se pudo encontrar datos coincidente

    ```

    ```

    FirmaSAT ATTRIBUTE -d -a Sello -e Comprobante -i cfdv33-signed-tfd.xml
    Nm+AyKSlay8Lg5Z++uSHQNLC6FUGB9KInjk9cm0I+n4Jwxwp2SwdEaRP6hTH+f2veoqm6Z
    ...aFplBE3LQrPda+DjM2296Mje0mvoX+KtQpHAUOZoCg==

    ```

* The `TimbreFiscalDigital` element is required to be version 1.1 for CFD v4.0/3.3. The data for the QRcode image is different, too.
* The hash algorithm in a v4.0/3.3 signature is required to be SHA-256 (the signature algorithm is `sha256WithRSAEncryption`).
In FirmaSAT, 
the hash algorithm used to form digests and signatures is chosen automatically depending on the type and version of the document detected.
* The `NoCertificado` node is now included in the pipe string (cadena original) and *must* be completed before computing the digest or signing the document.
This must match the actual certificate used for signing.
In v3.2 you could use `00000000000000000000` as a placeholder; this no longer applies with v4.0/3.3.

    + Use [InsertCertificateDetails](#InsertCertificateDetails) to insert the certificate details 
        	(`NoCertificado` and `Certificado`)
        	before doing further work.

* The XSD validation of a v4.0/3.3 document refers to huge XSD catalog files. See [Checks against XSD catalog files](#checkcatalogs).
* FirmaSAT is designed to produce digital signatures and analyze XML documents for correct structure and missing attributes.
It does *not* carry out any further checks such as those in the guidelines 
[GuíaAnexo20.pdf](https://cryptosys.net/firmasat/docs/GuiaAnexo20.pdf "External link") (local copy, 3.6 MB, 
[official link](http://m.sat.gob.mx/informacion_fiscal/factura_electronica/Documents/Gu%C3%ADaAnexo20.pdf "External link"))
or
[Guia_comple_pagos.pdf](https://cryptosys.net/firmasat/docs/Guia_comple_pagos.pdf "External link") (local copy, 663 kB).
You must carry out any other checks independently.

<a id="keyfileformat"></a>Key file format
-----------------------------------------

*[New in v10.70]* FirmaSAT now supports unencrypted key files as well as the usual encrypted key files.
Detection of an unencrypted key file is automatic when performing signing and key checking operations. In these cases the password is ignored. Set it to the empty string
`szPassword=""` in your code or use `-p ""` in the CLI.
To save an encrypted file in unencrypted form, use [Save key file with a new password](#SaveKeyFile) but set the new password as the empty string `""`.

**Technical note:**
The standard key format issued by SAT is PKCS#8 encrypted key `EncryptedPrivateKeyInfo` represented in PEM textual form with the identifier
`BEGIN ENCRYPTED PRIVATE KEY`. The unencrypted form is PKCS#8 `PrivateKeyInfo` represented in PEM form with
`BEGIN PRIVATE KEY`.  
References: [RFC5208](https://datatracker.ietf.org/doc/html/rfc5208 "External link") and [RFC5958](https://datatracker.ietf.org/doc/html/rfc5958 "External link").

<a id="SignXML"></a>Sign XML
----------------------------

Signs an XML file. Creates the signature and sets the 'Sello' node in an XML file. 
  

Señales de un archivo XML. Crea la firma y se establece el «Sello» de nodo en un archivo XML.

| ```  <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/4" Version="4.0" ... NoCertificado="30001000000300023708" Certificado="" Sello="" ...>  ``` | → | ```  <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" Version="4.0" ... NoCertificado="30001000000300023708"  Certificado="MIIE/TCCA+WgAwIBAgIUMzAwMDEwMDAwMD..."  Sello="Gnm1yXaIig5hr1dJ+88gjLY5usQxXP2s..." ...>  ``` |
| --- | --- | --- |
| ```  <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" Version="3.3" ... NoCertificado="30001000000100000800" Certificado="" Sello="" ...>  ``` | → | ```  <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" Version="3.3" ... NoCertificado="30001000000100000800"  Certificado="MIIE/TCCA+WgAwIBAgIUMzAwMDEwMDAwMD..."  Sello="AyiGH1muK3mMdxL705tSpShxswu0OyGkg9L4AP03..." ...>  ``` |
| ```  <retenciones:Retenciones xmlns:retenciones="http://www.sat.gob.mx/esquemas/retencionpago/2" Version="2.0" ... NoCertificado="20001000000100005867" Certificado="" Sello="" ...>  ``` | → | ```  <retenciones:Retenciones  xmlns:retenciones="http://www.sat.gob.mx/esquemas/retencionpago/2" version="2.0" ... NoCertificado="20001000000100005867" Certificado="MIIEdDCCA1ygAwIBAgIUMj..." Sello="O0w5ZAoywGZMQWxowwSsJ..." ...>  ``` |
| ```  <controlesvolumetricos:ControlesVolumetricos xmlns:controlesvolumetricos="http://www.sat.gob.mx/esquemas/controlesvolumetricos" version="1.1" ... noCertificado="20001000000300003600" certificado="MIIFhjCCA26gAwIBA... sello="" ...>  ``` | → | ```  <controlesvolumetricos:ControlesVolumetricos  xmlns:controlesvolumetricos="http://www.sat.gob.mx/esquemas/controlesvolumetricos" version="1.1" ... noCertificado="20001000000300003600" certificado="MIIFhjCCA26gAwIBA..." sello="ggYOp3kBN+TXtO+vsheCM6i23wOp/NX..." ...>  ``` |

Note that the `NoCertificado` attribute in a CFDi document and `Retenciones` document *must* be set to the
correct certificate serial number before signing or computing the digest.
For a `ControlesVolumetricos` document both the `noCertificado` *and*
the `certificado` attributes must be set to match the certificate used to sign document.

#### Function index by language

| Cmd : | [SIGNXML Command](commandline.html#Cmd_SIGNXML) |
| --- | --- |
| .NET : | [Sat.SignXml Method](fsaDotNetManual.html#M_Sat_SignXml)   [Sat.SignXmlToBytes Method (String, ...)](fsaDotNetManual.html#M_Sat_SignXmlToBytes_StringStringStringStringSignOptions)   [Sat.SignXmlToBytes Method (Byte[], ...)](fsaDotNetManual.html#M_Sat_SignXmlToBytes_ByteStringStringStringSignOptions) |
| VBA/VB6 : | [satSignXml Function](basFirmaSAT.bas.manual.html#VB_satSignXml)    [satSignXmlToBytes](basFirmaSAT.bas.manual.html#VB_satSignXmlToBytes)   [satSignXmlToString](basFirmaSAT.bas.manual.html#VB_satSignXmlToString) |
| C (ANSI) : | [SAT_SignXml Function](diFirmaSat2_h_Ref.html#a36090ace5c7554beb0f2e49b329c6505)   [SAT_SignXmlToString Function](diFirmaSat2_h_Ref.html#a225f0e13640a227f301cfd22b755f220) |
| C++ (STL) : | [firmasat::Sat::SignXml](cppfsa/html/classfirmasat_1_1_sat.html#aa4d8411c410c16a57549282d04449174) |

### <a id="stricterchecksbeforesigning"></a>Stricter checks before signing

**Note:** [*New in v10.50*]
The SignXML functions now do additional checks on the structure of the XML document and check that all required nodes are present before signing. 
You are strongly recommended to use the [XMLOK/ValidateXml](#ValidateXMLDocument) functions on your base document before attempting to sign.

**Advanced users:** In the event that you need to override this strict behaviour to sign a document 
(that is, you *know* the node shown as required is really optional)
then use the `SAT_XML_OVERRIDE_REQD`/`SignOptions.OverrideReqd` option.
This is intended as an "emergency" option.

<a id="MakeSignature"></a>Make Signature
----------------------------------------

Creates the signature as a base64 string from data in an XML file ready to be inserted as a 'Sello' node. 
  

Crea la firma como una cadena base64 partir de los datos en un archivo XML listo para ser insertado como un «Sello» sobre el terreno.

#### Function index by language

| Cmd : | [MAKESIG Command](commandline.html#Cmd_MAKESIG) |
| --- | --- |
| .NET : | [Sat.MakeSignatureFromXml Method](fsaDotNetManual.html#M_Sat_MakeSignatureFromXml) |
| VBA/VB6 : | [satMakeSignatureFromXml Function](basFirmaSAT.bas.manual.html#VB_satMakeSignatureFromXml) |
| C (ANSI) : | [SAT_MakeSignatureFromXmlEx Function](diFirmaSat2_h_Ref.html#aaf8106314f0d6dc5c004be778c7b6f7e) |
| C++ (STL): | [firmasat::Sat::MakeSignatureFromXml](cppfsa/html/classfirmasat_1_1_sat.html#a246749432bea44e0af700dfcdb04a0d4) |

<a id="VerifyXMLSignature"></a>Verify XML Signature
---------------------------------------------------

Verifies the signature ('sello') in an XML file.  
  

Comprueba la firma («Sello») en un archivo XML.

**Important:**
The VERIFYSIG command and VerifySignature functions will verify that the signature (*Sello*) in the XML document
was created by the owner of the private key corresponding to the X.509 certificate (*Certificado*)
and that the correct digest has been used according to the SAT version number.

Nothing else is checked: dates, certificate expiry, certificate revocation, RFC number, validity of version as at date of issue.
The SAT validator sites may do extra tests that indicate a Comprobante is invalid even if it passes the FirmaSAT tests.

#### Function index by language

| Cmd : | [VERIFYSIG Command](commandline.html#Cmd_VERIFYSIG) |
| --- | --- |
| .NET : | [Sat.VerifySignature Method (String)](fsaDotNetManual.html#M_Sat_VerifySignature_String)   [Sat.VerifySignature Method (String, String)](fsaDotNetManual.html#M_Sat_VerifySignature_StringString) |
| VBA/VB6 : | [satVerifySignature Function](basFirmaSAT.bas.manual.html#VB_satVerifySignature) |
| C (ANSI) : | [SAT_VerifySignature Function](diFirmaSat2_h_Ref.html#a3d629f8a8b2ebe5e9fe19fb7f6196f57) |
| C++ (STL) : | [firmasat::Sat::VerifySignature](cppfsa/html/classfirmasat_1_1_sat.html#ad610ad75264ea5b35511396cf26b8a3a) |

<a id="ValidateXMLDocument"></a>Validate XML Document
-----------------------------------------------------

Validates an XML file against SAT specifications.  
  

Valida un archivo XML contra S.A.T. especificaciones.

**Important:**
The XMLOK command and ValidateXml functions just check that the XML file is well-formed according to the corresponding
SAT specification. They do *not* verify the signature. 

There may be some attribute facets not detected that a more sophisticated XSD parser may find, and the SAT
validator sites may do extra checks not strictly in accordance with the XML standards.

If XMLOK/ValidateXml finds an error, then your input XML file definitely has a problem that needs fixing. 
	But we do not guarantee that an XML file shown as "OK" will pass all the tests on a SAT validator site.

See also [XML restriction violated: Element must be empty](#mustbeempty)

and [Checks against XSD catalogs](#checkcatalogs).

#### Function index by language

| Cmd : | [XMLOK Command](commandline.html#Cmd_XMLOK) |
| --- | --- |
| .NET : | [Sat.ValidateXml Method](fsaDotNetManual.html#M_Sat_ValidateXml) |
| VBA/VB6 : | [satValidateXml Function](basFirmaSAT.bas.manual.html#VB_satValidateXml) |
| C (ANSI) : | [SAT_ValidateXml Function](diFirmaSat2_h_Ref.html#a4b8adc02f32e67ea7065adef82f73848) |
| C++ (STL) : | [firmasat::Sat::ValidateXml](cppfsa/html/classfirmasat_1_1_sat.html#ae10c14c29da6759a3a038cced8261ae1) |

### <a id="mustbeempty"></a>XML restriction violated: Element must be empty

If you get an error of the form:

```

XML restriction is violated/XML restriccion es violada: Element [cfdi:Traslados/cfdi:Traslado] must be empty/El elemento debe estar vacio.

```

or

```

cvc-complex-type.2.1: Element 'cfdi:Traslado' must have no character or element information item [children], because the type's content type is empty.	

```

This is because extra whitespace has been added inside an element that must be empty.
For example,

```

<cfdi:Traslado Base="2250000" Impuesto="002" TipoFactor="Tasa" TasaOCuota="1.600000" Importe="360000">
  </cfdi:Traslado>

```

has white space after the end of the opening tag `>` and before start of the closing tag `</cfdi:Traslado>`,
but the element must be empty. 
The correct form should be

```

<cfdi:Traslado Base="2250000" Impuesto="002" TipoFactor="Tasa" TasaOCuota="1.600000" Importe="360000"></cfdi:Traslado>

```

FirmaSAT will never produce output with that error (unless it's there in the first place).
Do not attempt to reformat or "prettify" the XML output after signing.

### <a id="checkcatalogs"></a>Checks against XSD catalog files

[*New in v9.0*] 
The [ValidateXMLDocument](#ValidateXMLDocument) (`XMLOK`) functions will now check against the huge catCFDI.xsd and other XSD catalogs.
There is a small chance (less than 1 in 100) of a false positive, where an incorrect attribute value is passed as valid. 
However, if an attribute value is rejected as not in the catalog then it is definitely an error.
Formerly, only general checks on the pattern of the value were made. 

<a id="MakePipeString"></a>Make Pipe String
-------------------------------------------

Creates the "pipe" string (`cadena`) from an XML file
  

Crea la secuencia de la pipa (`cadena`) de un archivo XML.

#### Function index by language

| Cmd : | [PIPESTRING Command](commandline.html#Cmd_PIPESTRING) |
| --- | --- |
| .NET : | [Sat.MakePipeStringFromXml Method](fsaDotNetManual.html#M_Sat_MakePipeStringFromXml) |
| VBA/VB6 : | [satMakePipeStringFromXml Function](basFirmaSAT.bas.manual.html#VB_satMakePipeStringFromXml) |
| C (ANSI) : | [SAT_MakePipeStringFromXml Function](diFirmaSat2_h_Ref.html#a19381f294574cb0d301d982ccd4692bc) |
| C++ (STL) : | [firmasat::Sat::MakePipeStringFromXml](cppfsa/html/classfirmasat_1_1_sat.html#a01a789d40e68ebda4d68bc6ae4391330) |

<a id="MakeDigest"></a>Make Digest
----------------------------------

Computes the message digest of pipe string (`cadena`) from an XML file. 
  

Calcula el resumen del mensaje de la secuencia de la pipa ("Cadena") de un archivo XML.

#### Function index by language

| Cmd : | [FORMDIGEST Command](commandline.html#Cmd_FORMDIGEST) |
| --- | --- |
| .NET : | [Sat.MakeDigestFromXml Method](fsaDotNetManual.html#M_Sat_MakeDigestFromXml_String) |
| VBA/VB6 : | [satMakeDigestFromXml Function](basFirmaSAT.bas.manual.html#VB_satMakeDigestFromXml) |
| C (ANSI) : | [SAT_MakeDigestFromXml Function](diFirmaSat2_h_Ref.html#a487772b72bfb230f707a7d9e6a913a98) |
| C++ (STL) : | [firmasat::Sat::MakeDigestFromXml](cppfsa/html/classfirmasat_1_1_sat.html#a751a1a9cb698b98a224cc65ba6785c38) |

<a id="ExtractDigestFromSignature"></a>Extract Digest From Signature
--------------------------------------------------------------------

Extracts the message digest from the signature ('Sello') in an XML file.
  

Extractos del resumen del mensaje de la firma («Sello») en un archivo XML.

#### Function index by language

| Cmd : | [EXTRACTDIGEST Command](commandline.html#Cmd_EXTRACTDIGEST) |
| --- | --- |
| .NET : | [Sat.ExtractDigestFromSignature Method](fsaDotNetManual.html#M_Sat_ExtractDigestFromSignature_String)   [Sat.ExtractDigestFromSignature Method (String, String)](fsaDotNetManual.html#M_Sat_ExtractDigestFromSignature_StringString) |
| VBA/VB6 : | [satExtractDigestFromSignature Function](basFirmaSAT.bas.manual.html#VB_satExtractDigestFromSignature) |
| C (ANSI) : | [SAT_ExtractDigestFromSignature Function](diFirmaSat2_h_Ref.html#a6f71e5531e237b939031724f612a3c10) |
| C++ (STL) : | [firmasat::Sat::ExtractDigestFromSignature](cppfsa/html/classfirmasat_1_1_sat.html#a6f73d7dfe310c94ab432381f655683e5) |

<a id="InsertCertificateDetails"></a>Insert Certificate Details
---------------------------------------------------------------

Inserts certificate details into an XML file.
  

Insertar detalles de certificado en un archivo XML.

#### Function index by language

| Cmd : | [INSERTCERT Command](commandline.html#Cmd_INSERTCERT) |
| --- | --- |
| .NET : | [Sat.InsertCert Method](fsaDotNetManual.html#M_Sat_InsertCert)   [Sat.InsertCertToBytes Method (Byte[], String)](fsaDotNetManual.html#M_Sat_InsertCertToBytes_ByteString)   [Sat.InsertCertToBytes Method (String, String)](fsaDotNetManual.html#M_Sat_InsertCertToBytes_StringString) |
| VBA/VB6 : | [satInsertCertToString Function](basFirmaSAT.bas.manual.html#VB_satInsertCertToString) |
| C (ANSI) : | [SAT_InsertCert Function](diFirmaSat2_h_Ref.html#a17b2c15c38fbf7db7cb59d2df4bfae19)    [SAT_InsertCertToString Function](diFirmaSat2_h_Ref.html#a4d31e8a8f046537913aa9f9fa955e99e) |
| C++ (STL) : | [firmasat::Sat::InsertCert](cppfsa/html/classfirmasat_1_1_sat.html#a4c007776d2f1d7fb105bf7eb75645a2e) |

<a id="GetCertificateAsAString"></a>Get Certificate as a String
---------------------------------------------------------------

Gets the certificate data as a base64 string.
  

Obtiene los datos del certificado como una cadena base64.

#### Function index by language

| Cmd : | [CERTSTRING Command](commandline.html#Cmd_CERTSTRING) |
| --- | --- |
| .NET : | [Sat.GetCertAsString Method](fsaDotNetManual.html#M_Sat_GetCertAsString) |
| VBA/VB6 : | [satGetCertAsString Function](basFirmaSAT.bas.manual.html#VB_satGetCertAsString) |
| C (ANSI) : | [SAT_GetCertAsString Function](diFirmaSat2_h_Ref.html#ae465727fa462736dcd3c455428984e40) |
| C++ (STL) : | [firmasat::Sat::GetCertAsString](cppfsa/html/classfirmasat_1_1_sat.html#a603c5e874916ba76fb8fbc16d894d19d) |

<a id="GetCertificateSerialNumber"></a>Get Certificate Serial Number
--------------------------------------------------------------------

Gets the serial number of the X.509 certificate in "special" SAT format. 
  

Obtiene el número de serie del certificado X.509 en "especial" SAT formato.

#### Function index by language

| Cmd : | [NUMBERCERT Command](commandline.html#Cmd_NUMBERCERT) |
| --- | --- |
| .NET : | [Sat.GetCertNumber Method](fsaDotNetManual.html#M_Sat_GetCertNumber) |
| VBA/VB6 : | [satGetCertNumber Function](basFirmaSAT.bas.manual.html#VB_satGetCertNumber) |
| C (ANSI) : | [SAT_GetCertNumber Function](diFirmaSat2_h_Ref.html#ae7ffc001056d22de5102046a581b01bb) |

<a id="GetCertificateValidityDates"></a>Get Certificate Validity Dates
----------------------------------------------------------------------

Gets the expiry/start date of the X.509 certificate in ISO time format
  

Obtiene la expiración / fecha de inicio del certificado X.509 en el formato de la ISO.

#### Function index by language

| .NET : | [Sat.GetCertExpiry Method](fsaDotNetManual.html#M_Sat_GetCertExpiry) |
| --- | --- |
| VBA/VB6 : | [satGetCertExpiry Function](basFirmaSAT.bas.manual.html#VB_satGetCertExpiry) |
| C (ANSI) : | [SAT_GetCertExpiry Function](diFirmaSat2_h_Ref.html#a7a7f455852ada5242dad620ad59e777f) |

<a id="querycert"></a>Query a Certificate
-----------------------------------------

Queries an X.509 certificate for a given value. 
  

Búsquedas un certificado X.509 para un valor dado.

#### Function index by language

| Cmd : | [QUERYCERT Command](commandline.html#Cmd_QUERYCERT) |
| --- | --- |
| .NET : | [Sat.QueryCert Method](fsaDotNetManual.html#M_Sat_QueryCert) |
| VBA/VB6 : | [satQueryCert Function](basFirmaSAT.bas.manual.html#VB_satQueryCert) |
| C (ANSI) : | [SAT_QueryCert Function](diFirmaSat2_h_Ref.html#a8c7dbea0b2bf9ff33000ca831654d857) |
| C++ (STL) : | [firmasat::Sat::QueryCert](cppfsa/html/classfirmasat_1_1_sat.html#a34a173275cf78876debecdb47d592a32) |

| Query | Result |
| --- | --- |
| **notAfter** | Get certificate expiry date |
| **notBefore** | Get certificate start date |
| **organizationName** | Get organization name of issuer.  		Expecting "Servicio de Administración Tributaria" if issued by SAT |
| **orgName** | Shorter form of **organizationName** |
| **companyName** | Get organization name of subject. This should be your company name. *New in [v10.40]* |
| **rfc** | Get RFC of subject. Expecting 12 or 13 characters if issued by SAT. |
| **serialNumber** | Get decoded serial number. Expecting 20 decimal digits if issued by SAT. |
| **sigAlg** | Get algorithm used to sign certificate (e.g. "sha256WithRSAEncryption") |
| **keySize** | Get size in bits of certificate's public key (e.g. "2048") |

Note that the **sigAlg** option gives the algorithm used to sign the *certificate*, 
not the algorithm used for the `sello` node.

<a id="GetXMLAttribute"></a>Get XML Attribute
---------------------------------------------

Extracts attribute data from an XML file 
  

Extractos atributo de datos desde un archivo XML.

This will extract the value of the attribute with *attributeName* specified in the first element matching the given *elementName*. 
If no match is found, it will return an error `NO_MATCH_ERROR` or `"!NO MATCH!"`.
The default behaviour is to use the *first* element found that matches the given element name.
More specific elements can be specified using an [xpath expression](#xpathexpression).

**Special cases:**
To test for the existence of an element, specify `attributeName=""`. This will return the (qualified) name of the element if found, or `NO_MATCH_ERROR` if not found.
Setting elementName="" will output the named attribute from the root element of the XML document. 
Setting both elementName="" and attributeName="" will output the name of the root element itself.

#### Function index by language

| Cmd : | [ATTRIBUTE Command](commandline.html#Cmd_ATTRIBUTE) |
| --- | --- |
| .NET : | [Sat.GetXmlAttribute Method](fsaDotNetManual.html#M_Sat_GetXmlAttribute) |
| VBA/VB6 : | [satGetXmlAttribute Function](basFirmaSAT.bas.manual.html#VB_satGetXmlAttribute) |
| C (ANSI) : | [SAT_GetXmlAttributeEx Function](diFirmaSat2_h_Ref.html#aa046bd111fdb13b02fbbe47856aafde2) |
| C++ (STL) : | [firmasat::Sat::GetXmlAttribute](cppfsa/html/classfirmasat_1_1_sat.html#a430050f4ef7bb9a330df86b5bc3600f7) |

### <a id="xpathexpression"></a>Simplified XPath expressions for the elementName parameter

The elementName parameter in the GetXmlAttribute function now supports a simplified xpath expression to find attribute values in the more complicated structure of CFDiv3.3 XML documents.

#### Simple element name

Set the `elementName` argument to the simple name of the element to be found, e.g. `"Comprobante"` or `"cfdi:Comprobante"`. This will find the *first* occurence of the element anywhere in the document. To find the Nth element, write as `elementName[N]` where `N` is a positive decimal integer (`N=1,2,3,...`).
For example, `"Concepto[3]"` will find the third element named `Concepto` anywhere in the document.

Set `elementName` as the empty string `""` to specify the root element. Set both `elementName` and `attrname` to `""` to find the name of the root element.

#### XPath Expression

For a more detailed search, specify an **xpath expression** in the `elementName` parameter using the child path operator `"/"` and the descendant operator `"//"`, together with an optional element predicate of the form `[N]` where `N` is a positive integer (`N=1,2,3,...`).
For example, `"/Comprobante/Emisor"` or `"//Concepto[2]//Retencion[3]"`. 

### Simplified Xpath syntax:

* `/e1` -- selects the *first* `<e1>` document element (child element of the document node).
* `/e1/e2` -- selects the first `<e2>` child element of the first `<e1>` document element.
* `/e1[2]/e2[3]` -- selects the third `<e2>` child element of the second `<e1>` document element.
* `/e1[1]/e2[1]` -- same as `/e1/e2`.
* `//e2` -- the first `<e2>` element found anywhere (same as simple `e2`).
* `//e2[3]` -- the third `<e2>` element found anywhere (same as simple `e2[3]`).
* `/e1//e2` -- the first `<e2>` element found anywhere inside the `<e1>` element.

This behaviour is similar to XPath except it selects the *first* occurrence of the element matching the expression (whereas XPath would select *all* elements). The `elementName` xpath expression *must* begin with a `"/"` or `"//"` and must not end with a `"/"`. The expression `"//"` by itself is not valid. No other XPath function or operator is accepted - including the "@" operator. The required attribute name must be specified separately in the `attributeName` parameter.

Namespaces are ignored when matching against a path expression. A path element name with prefix - e.g. `"/cfdi:Comprobante"` - is invalid.

To test for the existence of an element, specify `attrname=""`. This will return the (qualified) name of the element if found, or `!NO MATCH!` if not found.

<a id="AsciifyXmlDocument"></a>Asciify an XML Document
------------------------------------------------------

Replace non-ASCII characters with XML character references.
  

Reemplazar caracteres no ASCII con referencias de caracteres XML.

In almost all cases, the output contains only US-ASCII characters and can safely be used as input to other functions without concern for character encoding issues. 
For example, the character "ó" (U+00F3 LATIN SMALL LETTER O WITH ACUTE) is replaced by the XML character reference "&#xF3;". 

In certain cases, some characters in an XML document cannot be replaced by a numeric character reference, 
for example where they used in an element or attribute *name*: Año="2016" or Antigüedad="P3Y2M23D".

*New in [v10.0]:* This function now converts all non-ASCII characters that can legitimately be converted to numeric character references, 
and any other non-ASCII characters are left encoded as appropriate for the programming language.

```

<cfdi:Emisor Rfc="AAA010101AAA" Nombre="Esta es una demostraci&#xF3;n" RegimenFiscal="622"></cfdi:Emisor>

```

```

<nomina12:Receptor Curp="OAAJ840102HJCVRN00" Antigüedad="P3Y2M23D" TipoContrato="01" Sindicalizado="S&#xED;" ... >
<nomina12:CompensacionSaldosAFavor SaldoAFavor="123.45" Año="2016" RemanenteSalFav="123.45"></nomina12:CompensacionSaldosAFavor>

```

#### Function index by language

| Cmd : | [ASCIIFY Command](commandline.html#Cmd_ASCIIFY) |
| --- | --- |
| .NET : | [Sat.Asciify Method ](fsaDotNetManual.html#M_Sat_Asciify_String) (String)   [Sat.Asciify Method ](fsaDotNetManual.html#M_Sat_Asciify_Byte) (Byte[]) |
| VBA/VB6 : | [satAsciify Function](basFirmaSAT.bas.manual.html#VB_satAsciify) |
| C (ANSI) : | [SAT_Asciify Function](diFirmaSat2_h_Ref.html#aa392d93554689389dcde249a113ffd02) |
| C++ (STL) : | [firmasat::Sat::Asciify](cppfsa/html/classfirmasat_1_1_sat.html#aab4251ec6c5320481e88df409266ebd0) |

<a id="GetPrivateKeyAsAString"></a>Get Private Key as a String
--------------------------------------------------------------

Gets the private key data as a base64 string.
  

Obtiene los datos de la clave privada en forma de cadena base64.

#### Function index by language

| Cmd : | [GETKEYSTRING Command](commandline.html#Cmd_GETKEYSTRING) |
| --- | --- |
| .NET : | [Sat.GetKeyAsString Method](fsaDotNetManual.html#M_Sat_GetKeyAsString) |
| VBA/VB6 : | [satGetKeyAsString Function](basFirmaSAT.bas.manual.html#VB_satGetKeyAsString) |
| C (ANSI) : | [SAT_GetKeyAsString Function](diFirmaSat2_h_Ref.html#aa517f7c0cbf0fedf5a785abe8ceeea1b) |
| C++ (STL) : | [firmasat::Sat::GetKeyAsString](cppfsa/html/classfirmasat_1_1_sat.html#ae137dd8f6a1136bca8faddf7610dcf64) |

***WARNING:*** Giving this data to an untrusted third party is a major security risk.

<a id="SaveKeyFile"></a>Save key file with a new password
---------------------------------------------------------

Save key file with a new password.
  

Guarde el archivo clave con una nueva contraseña.

#### Function index by language

| Cmd : | [NEWKEY Command](commandline.html#Cmd_NEWKEY) |
| --- | --- |
| .NET : | [Sat.NewKeyFile Method](fsaDotNetManual.html#M_Sat_NewKeyFile) |
| VBA/VB6 : | [satNewKeyFile Function](basFirmaSAT.bas.manual.html#VB_satNewKeyFile) |
| C (ANSI) : | [SAT_NewKeyFile Function](diFirmaSat2_h_Ref.html#ab2af43e63e5e037829e467f5da9aced3) |
| C++ (STL) : | [firmasat::Sat::NewKeyFile](cppfsa/html/classfirmasat_1_1_sat.html#a4f25194eea60c6fafa1022c56322ebfb) |

To save the key file in unencrypted form ("PrivateKeyInfo") set the new password to the empty string `szNewPassword=""` in your code or `-n ""` in the CLI.

<a id="writepfxfile"></a>Make a PFX File
----------------------------------------

Creates a PFX (PKCS-12) file in base64 format suitable for a Cancelación.
  

Crea un PFX (PKCS-12) archivo en formato base64 adecuado para una cancelación.

#### Function index by language

| Cmd : | [WRITEPFX Command](commandline.html#Cmd_WRITEPFX) |
| --- | --- |
| .NET : | [Sat.WritePfxFile Method](fsaDotNetManual.html#M_Sat_WritePfxFile) |
| VBA/VB6 : | [satWritePfxFile Function](basFirmaSAT.bas.manual.html#VB_satWritePfxFile) |
| C (ANSI) : | [SAT_WritePfxFile Function](diFirmaSat2_h_Ref.html#a39cfceaf54c288553d9e0bbf5d489725) |
| C++ (STL) : | [firmasat::Sat::WritePfxFile](cppfsa/html/classfirmasat_1_1_sat.html#a2dce647f699105211b45e45726f1d46f) |

The default output file will be identical in format to the final output from the following sequence of OpenSSL commands
(without the intermediate files!): 

```

x509 -inform DER -in certificado.cer -out certificado.pem
pkcs8 -inform DER -in llave.key -passin pass:miclave -out llave.pem
pkcs12 -export -out archivo.pfx -inkey llave.pem -in certificado.pem -passout pass:clavedesalida
base64 -in archivo.pfx -out archivo.pem

```

***WARNING:*** Giving this PFX file and its password to an untrusted third party is a major security risk.

<a id="checkkeyandcert"></a>Check Key and Certificate
-----------------------------------------------------

Verifies that the public key in an X.509 certificate matches the private key.
  

Comprueba que la clave pública en un certificado X.509 coincida con la clave privada.

#### Function index by language

| Cmd : | [KEYCHECK Command](commandline.html#Cmd_KEYCHECK) |
| --- | --- |
| .NET : | [Sat.CheckKeyAndCert Method](fsaDotNetManual.html#M_Sat_CheckKeyAndCert) |
| VBA/VB6 : | [satCheckKeyAndCert Function](basFirmaSAT.bas.manual.html#VB_satCheckKeyAndCert) |
| C (ANSI) : | [SAT_CheckKeyAndCert Function](diFirmaSat2_h_Ref.html#acb2774178c116e0f93612b5d4d42e439) |
| C++ (STL) : | [firmasat::Sat::CheckKeyAndCert](cppfsa/html/classfirmasat_1_1_sat.html#a40f2c20be1f5b9ada76702b09521285b) |

<a id="getxmlreceiptversion"></a>Get XML Receipt Version Number
---------------------------------------------------------------

Get receipt ('Comprobante') version number from XML file or ID number for other document types.
  

Obtener recibo («Comprobante») número de versión de archivo XML o número de identificación para otros tipos de documentos.

* 40 = Comprobante document with Version="4.0"
* 33 = Comprobante document with Version="3.3" (legacy)
* 32 = Comprobante document with version="3.2" (legacy)
* 1010/1020 = Retenciones document with Version="1.0"/"2.0"
* 2011/2013 = CatalogoCuentas  document with Version="1.1"/"1.3"
* 2111/2113 = BalanzaComprobacion  document with Version="1.1"/"1.3"
* 2211/2213 = PolizasPeriodo  document with Version="1.1"/"1.3"
* 2312/2313 = AuxiliarFolios document with Version="1.2"/"1.3"
* 2411/2413 = AuxiliarCtas document with Version="1.1"/"1.3"
* 2511 = SelloDigitalContElec  document with Version="1.1"
* 4011 = ControlesVolumetricos document with Version="1.1"

#### Function index by language

| Cmd : | [RECEIPTVERSION Command](commandline.html#Cmd_RECEIPTVERSION) |
| --- | --- |
| .NET : | [Sat.XmlReceiptVersion Method](fsaDotNetManual.html#M_Sat_XmlReceiptVersion) |
| VBA/VB6 : | [satXmlReceiptVersion Function](basFirmaSAT.bas.manual.html#VB_satXmlReceiptVersion) |
| C (ANSI) : | [SAT_XmlReceiptVersion Function](diFirmaSat2_h_Ref.html#ade3d50c17b34fc45c966badf64952297) |
| C++ (STL) : | [firmasat::Sat::XmlReceiptVersion](cppfsa/html/classfirmasat_1_1_sat.html#ac58c9383b26702a5412d2f573bcefe31) |

<a id="fixutf8bom"></a>Fix UTF-8 BOM
------------------------------------

Adds a UTF-8 byte-order mark (BOM) to an existing file.
  

Añade un byte UTF-8 marca de orden (BOM) a un archivo existente.

#### Function index by language

| Cmd : | [UTF8FIX Command](commandline.html#Cmd_UTF8FIX) |
| --- | --- |
| .NET : | [Sat.FixBom Method](fsaDotNetManual.html#M_Sat_FixBom) |
| VBA/VB6 : | [satFixBOM Function](basFirmaSAT.bas.manual.html#VB_satFixBOM) |
| C (ANSI) : | [SAT_FixBOM Function](diFirmaSat2_h_Ref.html#ae9372d1895bf7583bb16ed0257c07e17) |
| C++ (STL) : | [firmasat::Sat::FixBOM](cppfsa/html/classfirmasat_1_1_sat.html#aa6d651f37f09eec1551d1e71370df9cb) |

<a id="generateuuid"></a>Generate a UUID
----------------------------------------

Generate a Universally Unique IDentifier (UUID) compliant with RFC 4122.
  

Generar un identificador único universal (UUID) compatible con RFC 4122.

#### Function index by language

| Cmd : | [UUID Command](commandline.html#Cmd_UUID) |
| --- | --- |
| .NET : | [Sat.Uuid Method](fsaDotNetManual.html#M_Sat_Uuid) |
| VBA/VB6 : | [satUuid Function](basFirmaSAT.bas.manual.html#VB_satUuid) |
| C (ANSI) : | [SAT_Uuid Function](diFirmaSat2_h_Ref.html#a60f6a8a30ab85abf5e33696c6374aaa2) |
| C++ (STL) : | [firmasat::Sat::Uuid](cppfsa/html/classfirmasat_1_1_sat.html#a896bf746657844d4f8945c4b48c173f1) |

<a id="tfdelement"></a>Timbre Fiscal Digital (TFD) element
----------------------------------------------------------

The TFD option operates on the `tfd:TimbreFiscalDigital` (TFD) element instead of the `cfdi:Comprobante`.
Use to create the TFD pipestring (*cadena original del timbre fiscal digital del SAT*)
and verify the `selloSAT` signature.
  

La opción de TFD actúa sobre el elemento de `tfd:TimbreFiscalDigital` (TFD) 
en lugar del elemento `cfdi:Comprobante`.
Se utiliza para crear la *cadena original del timbre fiscal digital del SAT*
y verificar la firma `selloSAT`.

Use the "`-f`" option in the commands 
[`PIPESTRING`](#MakePipeString),
[`VERIFYSIG`](#VerifyXMLSignature),
[`EXTRACTDIGEST`](#ExtractDigestFromSignature),
[`FORMDIGEST`](#MakeDigest) and
[`MAKESIG`](#MakeSignature). 

For example, the following command will output the TFD pipestring (cadena original del timbre fiscal digital del SAT)
from the `tfd` element (provided the element exists).

```

FirmaSAT PIPESTRING -f cfdv33a-signed-tfd.xml

```

```

||1.1|b2e2c132-01d6-4c62-a158-7ac932d0ec36|...

```

Use the `SAT_TFD` option in the VB6/C functions

* [`SAT_MakePipeStringFromXml`](diFirmaSat2_h_Ref.html#a19381f294574cb0d301d982ccd4692bc)
* [`SAT_VerifySignature`](diFirmaSat2_h_Ref.html#a3d629f8a8b2ebe5e9fe19fb7f6196f57)
* [`SAT_ExtractDigestFromSignature`](diFirmaSat2_h_Ref.html#a6f71e5531e237b939031724f612a3c10)
* [`SAT_MakeDigestFromXml`](diFirmaSat2_h_Ref.html#a487772b72bfb230f707a7d9e6a913a98)
* [`SAT_MakeSignatureFromXmlEx`](diFirmaSat2_h_Ref.html#aaf8106314f0d6dc5c004be778c7b6f7e)

```

nchars = SAT_MakePipeStringFromXml(buf, nchars, fname, SAT_TFD);

```

Use the "tfd" wrapper functions in VBA/VB6:

* [tfdMakePipeStringFromXml](basFirmaSAT.bas.manual.html#VB_tfdMakePipeStringFromXml)
* [tfdMakeDigestFromXml](basFirmaSAT.bas.manual.html#VB_tfdMakeDigestFromXml)
* [tfdExtractDigestFromSignature](basFirmaSAT.bas.manual.html#VB_tfdExtractDigestFromSignature)
* [tfdMakeSignatureFromXml](basFirmaSAT.bas.manual.html#VB_tfdMakeSignatureFromXml)
* [tfdVerifySignature](basFirmaSAT.bas.manual.html#VB_tfdVerifySignature)

Use the `Tfd Class` in C# and `VB.NET` with the methods

* [Tfd.MakePipeStringFromXml](#M_Tfd_MakePipeStringFromXml)
* [Tfd.MakeDigestFromXml](#M_Tfd_MakeDigestFromXml)
* [Tfd.MakeSignatureFromXml](#M_Tfd_MakeSignatureFromXml)
* [Tfd.ExtractDigestFromSignature](#M_Tfd_ExtractDigestFromSignature)
* [Tfd.VerifySignature](#M_Tfd_VerifySignature)

These methods work in exactly the same way as the equivalent methods in the Sat Class, except they operate on an existing TFD element, not the Comprobante. 
The certificate parameter is compulsory for the VerifySignature and ExtractDigestFromSignature methods.

#### Adding a new TFD element

If you want to add a new signed TFD element to a signed CFDI document,
see [Adding a TFD element](#addtfd) 
and the `[Tfd.AddSignedTfd](#M_Tfd_AddSignedTfd)` method.

<a id="addtfd"></a>Adding a TFD element
---------------------------------------

You can add a signed TimbreFiscalDigital (TFD) element to a signed CFDI document using the key and certificate of a PAC. 

  

Agrega una TimbreFiscalDigital (TFD) Elemento firmado a un documento firmado CFDI utilizando la clave y el certificado de un PAC.

The existing CFDI document must already have been signed by the issuer with a `sello` field.
The new TFD element will have a new UUID (different each time) and be timestamped with the system clock.
The `selloSAT` signature is created using the supplied key and certificate pair, either for a genuine PAC or for testing purposes.
Only version 3.2/3.3 CFDI documents with full `cfdi:` namespace prefixes can be used.

#### SIGNXML command

Use the "`-f`" option in the [`SIGNXML`](#SignXML) command.

```

FirmaSAT SIGNXML -f -s @ -k pac.key -p 12345678a -c pac.cer -i V3_2-signed.xml -o V3_2-tfd.xml

```

#### C/C++ SAT_SignXml() function

Use the `SAT_TFD` option with the [SAT_SignXml](diFirmaSat2_h_Ref.html#a36090ace5c7554beb0f2e49b329c6505) function.

```

printf("\nADD A TFD ELEMENT TO A SIGNED CFDI DOCUMENT USING PAC KEY: \n");
fname   = "V3_2-signed.xml";
newname = "V3_2-tfd.xml";
certfile = "pac.cer";
keyfile = "pac.key";
password = "12345678a";
n = SAT_SignXml(newname, fname, keyfile, password, certfile, SAT_TFD);
printf("SAT_SignXml(SAT_TFD, '%s'-->'%s') returns %ld\n", fname, newname, n);
assert(n == 0);

```

#### VB6/VBA SAT_SignXml() function

```

Debug.Print (vbLf & "ADD A TFD ELEMENT TO A SIGNED CFDI DOCUMENT USING PAC KEY:")
fname = "V3_2-signed.xml"
newname = "V3_2-tfd.xml"
certfile = "pac.cer"
keyfile = "pac.key"
password = "12345678a"    ' CAUTION: DO NOT HARD-CODE REAL PASSWORDS!
n = SAT_SignXml(newname, fname, keyfile, password, certfile, SAT_TFD)
Debug.Print "SAT_SignXml(SAT_TFD, '" & fname & "'-->'" & newname & "') returns " & n

```

<a id="bigfileoption"></a>BIGFILE option
----------------------------------------

The BIGFILE option speeds up processing on large files. 

*Caution:* the input and output files must be different if you use this option.

Use the "`-b`" option in the commands 
[`SIGNXML`](#SignXML),
[`VERIFYSIG`](#VerifyXMLSignature),
[`FORMDIGEST`](#MakeDigest) and
[`MAKESIG`](#MakeSignature). 

Use the `SAT_FILE_BIGFILE` option in the VB6/C functions

* [`SAT_SignXml`](diFirmaSat2_h_Ref.html#a36090ace5c7554beb0f2e49b329c6505)
* [`SAT_VerifySignature`](diFirmaSat2_h_Ref.html#a3d629f8a8b2ebe5e9fe19fb7f6196f57)
* [`SAT_MakeDigestFromXml`](diFirmaSat2_h_Ref.html#a487772b72bfb230f707a7d9e6a913a98)
* [`SAT_MakeSignatureFromXmlEx`](diFirmaSat2_h_Ref.html#aaf8106314f0d6dc5c004be778c7b6f7e)

Use the `SignOptions.BigFile` option in the .NET method 
[`Sat.SignXmlEx`](fsaDotNetManual.html#M_Sat_SignXmlEx).

<a id="diagnosticprocs"></a>Diagnostic Procedures
-------------------------------------------------

Get details about the core DLL library file. Use these for debugging.
  

Obtiene detalles sobre el archivo de la biblioteca DLL de Core. Utilice estos para la depuración.

#### Function index by language

| Cmd : | [LIBINFO Command](#Cmd_LIBINFO) |
| --- | --- |
| .NET : | [General.Version Method](fsaDotNetManual.html#M_General_Version)   [General.CompileTime Method](fsaDotNetManual.html#M_General_CompileTime)   [General.ModuleName Method](fsaDotNetManual.html#M_General_ModuleName)   [General.LicenceType Method](fsaDotNetManual.html#M_General_LicenceType)   [General.Platform Method](fsaDotNetManual.html#M_General_Platform)   [General.Comments Method](fsaDotNetManual.html#M_General_Comments) |
| VBA/VB6 : | [satVersion Function](basFirmaSAT.bas.manual.html#VB_satVersion)   [satLicenceType Function](basFirmaSAT.bas.manual.html#VB_satLicenceType)   [satCompileTime Function](basFirmaSAT.bas.manual.html#VB_satCompileTime)   [satModuleName Function](basFirmaSAT.bas.manual.html#VB_satModuleName)   [satPlatform Function](basFirmaSAT.bas.manual.html#VB_satPlatform)   [satComments Function](basFirmaSAT.bas.manual.html#VB_satComments) |
| C (ANSI) : | [SAT_Version Function](diFirmaSat2_h_Ref.html#ac1b20f4bd513ddbc05e99442b54aa614)   [SAT_LicenceType Function](diFirmaSat2_h_Ref.html#a0388d6f736857c6c2892d9004f9e8bde) [SAT_ModuleName Function](diFirmaSat2_h_Ref.html#a7acfd53f27bfed44d0884d9757b1d98e)   [SAT_CompileTime Function](diFirmaSat2_h_Ref.html#afe895ae180520a85133b1e90fcced6b8)   [SAT_Platform Function](diFirmaSat2_h_Ref.html#af9ae9dbe54d79d20c725f5bb454a5eb6)   [SAT_Comments Function](diFirmaSat2_h_Ref.html#ac2bdaa2ae237a4737857a565b0507fa0) |
| C++ (STL) : | [firmasat::Gen::Version](cppfsa/html/classfirmasat_1_1_gen.html#a4e1eca1e6cbd75686652a8243c72ee79)   [firmasat::Gen::CompileTime](cppfsa/html/classfirmasat_1_1_gen.html#a8e82855cb88221b453e4f3638227bc76)    [firmasat::Gen::ModuleName](cppfsa/html/classfirmasat_1_1_gen.html#ae2f8b17da656c30bc86016017913602f)    [firmasat::Gen::LicenceType](cppfsa/html/classfirmasat_1_1_gen.html#aaeb58c606133bf843b18414cf4c1319a)   [firmasat::Gen::Platform](cppfsa/html/classfirmasat_1_1_gen.html#a9b16d536f05befb7bddfdcb17ab0f2af)   [firmasat::Gen::Comments](cppfsa/html/classfirmasat_1_1_gen.html#a67c03a8f5af91c2898261fa11088830d) |

### <a id="Cmd_LIBINFO"></a>LIBINFO Command

```

FirmaSAT LIBINFO

```

If correctly installed, the output should be similar to:

```

FirmaSAT.exe v10.0.0 (Sep  8 2021 14:37:37).
Library diFirmaSAT2:
  Version:  100000
  Module:   C:\WINDOWS\SYSTEM32\diFirmaSAT2.dll
  Platform: Win32
  Compiled: Sep  8 2021 14:33:00
  Licence:  D
  Comments: Licensed Developer Edition | Edicion de Desarrollador Licenciado.

```

<a id="errorprocs"></a>Error-related procedures
-----------------------------------------------

Displays information about errors. 
  

Muestra información acerca de los errores.

The `ErrorLookup` function returns a description of a given error code.
The `LastError` function returns a description of the the last error that occurred (if available).
The `FormatErrorMessage` returns a general error message combining the results of the previous two functions.

```

Error (-28): XML restriction is violated/XML restriccion es violada (XML_FACET_ERROR):
Bad attribute/atributo mal [iedu:instEducativas/@CURP] (line 30):
'JUAN01010101GTOHMD0' is too long/es demasiado largo, maximum length/longitud maxima=18

```

#### Function index by language

| .NET : | [General.ErrorLookup Method](fsaDotNetManual.html#M_General_ErrorLookup)   [General.LastError Method](fsaDotNetManual.html#M_General_LastError)   [General.FormatErrorMessage Method](fsaDotNetManual.html#M_General_FormatErrorMessage) |
| --- | --- |
| VBA/VB6 : | [satErrorLookup Function](basFirmaSAT.bas.manual.html#VB_satErrorLookup)   [satLastError Function](basFirmaSAT.bas.manual.html#VB_satLastError)   [satFormatErrorMessage Function](basFirmaSAT.bas.manual.html#VB_satFormatErrorMessage) |
| C (ANSI) : | [SAT_ErrorLookup Function](diFirmaSat2_h_Ref.html#ad44d80a58cf8cd3ecbcff67a86301a7f)   [SAT_LastError Function](diFirmaSat2_h_Ref.html#a6a8b8b7558d48fed48a13e02616ef854) |
| C++ (STL) : | [firmasat::Err::ErrorLookup](cppfsa/html/classfirmasat_1_1_err.html#a054a956cd8975043dbe8a5be9ae4ba1c)   [firmasat::Err::LastError](cppfsa/html/classfirmasat_1_1_err.html#acaea7647b28e63b2c872fefe3f46abc5)   [firmasat::Err::FormatErrorMessage](cppfsa/html/classfirmasat_1_1_err.html#a4aba03b4407b74863f97d86972cd8e4c) |

<a id="errorcodes"></a>Error Codes
----------------------------------

This is a list of possible error codes returned by the FirmaSAT functions.
You can get the description for a given error code using the [`SAT_ErrorLookup`](diFirmaSat2_h_Ref.html#ad44d80a58cf8cd3ecbcff67a86301a7f) function
or the [`General.ErrorLookup`](#M_General_ErrorLookup) Method in .NET.
The [`SAT_LastError`](diFirmaSat2_h_Ref.html#a6a8b8b7558d48fed48a13e02616ef854) function and [Sat.LastError](fsaDotNetManual.html#M_Sat_LastError) method 
*usually* return a more detailed description of any error, but be warned that not all functions set this.

```

0 = OK, success, no error/OK, el exito, no hay error (SUCCESS_NO_ERROR)
1 = Cannot open input file/No se puede abrir archivo de entrada (OPEN_ERROR)
2 = Cannot create output file/No se puede crear archivo de salida (CREATE_ERROR)
3 = File read error/Error de lectura de archivos (READ_ERROR)
4 = File write error/Archivo de error de escritura (WRITE_ERROR)
5 = Not enough memory/No hay suficiente memoria (MEMORY_ERROR)
6 = Parameter is wrong or missing/El parametro es incorrecto o falta (BAD_PARAM_ERROR)
7 = Data in wrong format/Datos en formato incorrecto (BAD_FORMAT_ERROR)
8 = Invalid data/Datos invalidos (INVALID_DATA_ERROR)
9 = Unexpected end of file found/Fin inesperado del archivo encontrado (EOF_ERROR)
10 = Required data not found/Datos necesarios no encontrados (MISSING_ERROR)
12 = Duplicate data/Los datos duplicados (DUP_ERROR)
15 = Decryption error/De error de descifrado (DECRYPT_ERROR)
17 = Invalid option/Opcion no valida (BAD_FLAG_ERROR)
19 = Item is not supported/El articulo no es compatible (NOT_SUPPORTED_ERROR)
20 = No data found to process/No se han encontrado datos para procesar (NO_DATA_ERROR)
21 = Match not found/No se pudo encontrar datos coincidente (NO_MATCH_ERROR)
22 = Signature is invalid or missing/Firma no es valida o falta (SIGNATURE_ERROR)
23 = Failed self-integrity test/Error en la auto-prueba de integridad (TEST_FAILED_ERROR)
26 = Data not a valid length/Datos de una longitud no valida (BAD_LENGTH_ERROR)
27 = Invalid XML format/No valido formato XML (BAD_XML_ERROR)
28 = XML restriction is violated/XML restriccion es violada (XML_FACET_ERROR)
29 = Not a valid query/No es una consulta valida (BAD_QUERY_ERROR)
30 = Not enough room in output buffer/No suficiente espacio en el bufer de salida (SHORT_BUF_ERROR)
101 = Invalid X.509 certificate/No valido el certificado X.509 (BAD_CERT_ERROR)
102 = Internal error with XML parser/Error interno con el analizador de XML (PARSER_FAILED_ERROR)
103 = XML validator failed/XML validador no funciona (VALIDATOR_FAIL_ERROR)
104 = DTD file is invalid/Archivo DTD no es valida (BAD_DTD_ERROR)
105 = XML parsing error/Error de analisis XML (XML_PARSE_ERROR)
106 = Certificate numbers do not match/Los numeros de certificado no coinciden (CERT_NUM_ERROR)
9745 = Unexpected internal error/Error interno inesperado (INTERNAL_ERROR)
9999 = Miscellaneous error/Error miscelaneo (MISC_ERROR)

```

<a id="commandlineutility"></a>Command-line utility
---------------------------------------------------

The executable file `FirmaSAT.exe` must be in the environment PATH variable (which it should be). 
For more examples and the latest advice, 
go to our [command-line utility](commandline.html) page.

To see the syntax, open a command line console and type

```

FirmaSAT HELP

```

By default the output is sent to the console. To output to a file, use the "-o" option.

<a id="outputfilewarning"></a>
**WARNING:** The output file *must* be specified using the "-o" option.
This first example will not work.

```

FirmaSAT SIGNXML -k llave.key -p password -c certificado.cer muestra.xml muestra-signed.xml

```

But these next three examples are OK:

```

FirmaSAT SIGNXML -k llave.key -p password -c certificado.cer -o muestra-signed.xml muestra.xml 

```

```

FirmaSAT SIGNXML -k llave.key -p password -c certificado.cer -o muestra-signed.xml -i muestra.xml 

```

```

FirmaSAT SIGNXML -k llave.key -p password -c certificado.cer -i muestra.xml -o muestra-signed.xml 

```

### <a id="batchfile"></a>Example batch file

This shows one way to make a batch file (`SIGNIT.BAT`) that signs a given base XML file using a hard-coded key file and certificate name.
The password is correctly not hard-coded for security purposes. It can either be typed on the command line, or is prompted for.

```

@echo off
:: Expecting filename as first parameter...
if "%1"=="" GOTO NOFILE
SET MYFILE=%1
:: Deal with optional password and prompt if not given...
SET MYPWD=%2
if "%2"=="" set /P MYPWD=Enter password^>
:: Check if 64-bit machine and set PROGRAMFILES accordingly...
SET _pf=%PROGRAMFILES%
IF NOT "%PROGRAMFILES(X86)%"=="" SET _pf=%PROGRAMFILES(X86)%
REM ECHO %_pf%
:: Create output filename
FOR %%i IN (%MYFILE%) DO SET MYNEWFILE=%%~dpni-signed.xml
:: Do the business...
"%_pf%\FirmaSAT\FirmaSAT" SIGNXML -s @ -k emisor.key -p %MYPWD% -c emisor.cer -i %MYFILE% -o %MYNEWFILE%
SET MYPWD=
GOTO DONE
:NOFILE
echo ERROR: no filename
echo USAGE: %0 filename [password]
:DONE

```

This example will create a new file `base-signed.xml`.

```

SIGNIT base.xml a0123456789

```

<a id="cplusplusprogramming"></a>C/C++ Programming
--------------------------------------------------

To call from a C or C++ program using the ANSI C functions, add

```
#include diFirmaSAT2.h
```

to your source code
and link with the `diFirmaSAT2.lib` library.
For more details on the core functions you can call from C or C++, see the include file `diFirmaSAT2.h`
and the test code in `TestFirmaSat.c`, both included in the distribution.
If you get errors, see [Error codes](#errorcodes). 
Make sure you allocate memory for the output string buffers: see [Pre-dimensioning szOut](#predimensioningszout) below. 

```

#include <stdio.h>
#include "diFirmaSAT2.h"
int main(void) 
{
   long version;
   version = SAT_Version();
   printf("Version=%ld\n", version);
   return 0;
}

```

### <a id="predimensioningszout"></a>Pre-dimensioning szOut

Functions that provide output in `szOut` require the string to be pre-dimensioned to the required length
PLUS one extra for the NUL-terminating byte.
The functions return the total length of the string they tried to create. 
Passing a NULL `szOut` or zero `nOutChars` will return the required length of the output string in bytes 
EXCLUDING the NUL-terminating byte, so remember to add one if allocating memory in C. The length is correct for VB6. 
All output is UTF-8 encoded. 

For example:

```

long nChars;
char *lpszOut;
// Find out how many bytes we need
nChars = SAT_MakePipeStringFromXml(NULL, 0, xmlfile, 0);
if (nChars <= 0) error();
// Pre-dimension, i.e allocate memory for string buffer
lpszOut = malloc(nChars+1);  // NB +1
if (!lpszOut) error();
nChars = SAT_MakePipeStringFromXml(lpszOut, nChars, xmlfile, 0);
//...

```

<a id="cppprogramming"></a>C++ (STL) Programming
------------------------------------------------

The C++ (STL) interface to FirmaSAT is an interface to `diFirmaSat2.dll` for C++ programmers using STL (C++11 or above).

Required files to compile in a C++ project:

```

firmasat.hpp
diFirmaSat2.h
firmasat.cpp
  #include "diFirmaSat2.h"
  #include "firmasat.hpp"
{main}.cpp
  #include "firmasat.hpp"
  int main() { ... }

```

You must link to `diFirmaSAT2.lib`. In MSVC++ IDE, use `Project > Properties > Linker > Input > Additional Dependencies`
 and add the full path to `diFirmaSAT2.lib`. E.g.

```

Additional Dependencies = $(OutDir)diFirmaSAT2.lib;%(AdditionalDependencies)

```

Using the command-line with MSVC:

```

CL test.cpp firmasat.cpp /link ..\Debug\diFirmaSAT2.lib

```

Using GCC (make sure the DLL has been compiled for target X64):

```

g++ -std=c++11 test.cpp firmasat.cpp "C:\fullpath\to\x64\Debug\diFirmaSAT2.lib"

```

Here is a simple C++ (STL) program for testing.

```

#include <iostream>
#include "firmasat.hpp"
int main()
{
    std::cout << "Gen::Version=" << firmasat::Gen::Version() << std::endl;
}

```

<a id="vb6programming"></a>VB6/VBA Programming
----------------------------------------------

To use in a VB6 project or Microsoft Office VBA application, 
include the file `basFirmaSAT.bas` in your project and call the functions provided.
The "raw" functions beginning `SAT_` are identical to the C/C++ functions.

*New in [v10.0]:* 
There are now equivalent wrapper functions (beginning `sat`) for *all* the raw functions. 
These wrapper functions are safer and simpler to use and are the recommended interface.
The old "raw" SAT_ functions are deprecated for use in VBA/VB6 but retained for legacy purposes.

Here is a simple VBA/VB6 program for testing.

```

Public Sub ShowVersion()
   Dim nRet As Long
   nRet = satVersion()
   Debug.Print "Version=" & nRet
End Sub

```

<a id="vbnetprogramming"></a>`VB.NET`/VB2010+ programming
---------------------------------------------------------

To use in a `VB.NET`/VB2010+ program, add a reference to the .NET Class Library file
`diFirmaSatNet.dll` (usually installed in `C:\Program Files (x86)\FirmaSAT`)
and add the line

```

Imports FirmaSAT

```

at the top of your code. Here is a simple "Hello World" program.

```

Imports FirmaSAT
Module Module1
  Sub Main()
    Dim n As Integer
    n = General.Version()
    Console.WriteLine("Version = {0}", n)
  End Sub
End Module

```

<a id="csharpprogramming"></a>C# programming
--------------------------------------------

To use in a C# program, add a reference to the .NET Class Library file
`diFirmaSatNet.dll` (usually installed in `C:\Program Files (x86)\FirmaSAT`)
and add the line

```

using FirmaSAT;

```

at the top of your code. Here is a simple "Hello World" program.

```

using System;
using FirmaSAT;
class Program {
  static void Main() {
    int n = General.Version();
    Console.WriteLine("Version = {0}", n);
  }
}

```

Alternatively, instead of making a reference to the library DLL `diFirmaSatNet.dll`, you can include the interface library C# source code 
`diFirmaSatNet.cs` directly in your project and avoid any need for references.

---

<a id="changesinthis"></a>Changes in this version
-------------------------------------------------

Version 10.50 of FirmaSAT (2022-03):

* Added stricter checks for XML structure and required nodes before signing. See [Stricter checks before signing](#stricterchecksbeforesigning).
* Fixed optional/required issues for attributes in Retencion and Traslado elements.
* Updated example code to use v4.0 documents.
* Improved handing of UTF-8-encoded characters on command line.

### <a id="changesinolder"></a>Changes in older versions

Versions 10.40.1 to 10.40.24 of FirmaSAT (2021-12-20 to 2022-03-03):

* Updated for changes in Complemento Carta Porte v2.0 and catalog file catCartaPorte.xsd updated by S.A.T. 2021-12-31.
* Updated for various changes in S.A.T. catalog files.
* Added extra checks before signing.
* Fixed issue with optional Importe in Traslado.

Version 10.40 of FirmaSAT (2021-12-17):

* Added support for **CFDi versión 4.0**, Complemento Pagos v2.0 (Pagos20.xsd), and CFDI Retenciones v2.0 (retencionpago2.xsd).
* Removed support for legacy CFDi versions 2.0, 2.2 and 3.0.
* Added option `companyName` to QueryCert function to get certificate holder's "official" company name.
* Improved Command-line interface to handle non-ASCII characters (like ñ) in Windows console.

Versions 10.2.0 to 10.2.2 of FirmaSAT (2021-11-20 to 2021-12-04):

* Updated for changes in CartaPorte20.xsd and S.A.T. catalog file catComExt.xsd.

Version 10.1 of FirmaSAT (2021-11-07):

* Added support for Complemento Carta Porte v2.0 (CartaPorte20.xsd)

Version 10.0 of FirmaSAT (2021-09-08):

* Updated Command-line interface to handle UTF-8-encoded characters automatically in Windows console.

    + Options "-w" and "-1" for Windows default characters and Latin-1 encodings are now redundant and have been withdrawn.
* Added interface for C++ programmers using STL (C+11 and above).
* Consolidated .NET interface for C# and `VB.NET` programmers replacing overloaded methods with optional parameters.

    + Now requires .NET 4.0 and above - earlier versions were compatible with .NET 2.0. (That means compatibility with .NET only goes back 10 years instead of 16 years!)
        + No changes should be required for existing source code, except `Sat.SignXmlEx` is now deprecated in favour of the updated `Sat.SignXml`.
* Updated the VBA/VB6 interface to include all functions declarations for 32- and 64-bit versions in the one file `basFirmaSat.bas`.
* Provided a safer, more convenient VBA/VB6 wrapper function for *all* direct "raw" functions.
* Added options to WRITEPFX/WritePFXFile to allow output to both textual PEM files and binary DER PFX files.
* Added diagnostic `SAT_Platform` function.
* Added `FormatErrorMessage` function.
* Changed `Asciify` functions to output non-ASCII characters that cannot legally be converted to XML numeric character references in an encoding suitable for the programming language,
e.g. in UTF-8 for C and C++.
* Documentation is now provided as links to the web site rather than files included with the distribution. This reduces the size of the distribution and allows updates to be made more readily.

Versions 9.3.10 to 9.3.11 of FirmaSAT (2021-05-21 to 2021-07-21):

* Updated for changes in S.A.T. catalog files (catCFDI.xsd, catComExt.xsd, catNomina.xsd).

Version 9.3 of FirmaSAT (2021-05):

* Added support for new Complemento Carta Porte.
* Major updates to manual and other documentation.
* Re-compiled and re-signed all executables.

Versions 9.2.10 to 9.2.15 of FirmaSAT (2020-09-07 to 2021-02-21):

* Updated for changes in S.A.T. catalog files (catCFDI.xsd, catComExt.xsd, catNomina.xsd).

Version 9.2 of FirmaSAT (2020-08-06):

* Various improvements to solve UTF-8/UTF-16 encoding issues with input and output strings.
* Updated all functions to enable passing a .NET or VBA Unicode string as an argument for an XML document.
For example, the following C# code will now work properly for all XML files.
    > ```

    > string xmlStr = File.ReadAllText(xmlFile, Encoding.UTF8);
        > n = Sat.Validate(xmlStr);

    > ```

* .NET methods that return a string (e.g. Sat.QueryCert) now always return a valid .NET Unicode string.
* Improved the [Asciify](#AsciifyXmlDocument) function to address certain issues with XML numeric character references.
* Added options to output strings in Latin-1 encoding.

Versions 9.1.20 to 9.1.82 of FirmaSAT (2019-05-11 to 2020-08-05):

* Updated for changes in S.A.T. catalog files (catCFDI.xsd, catComExt.xsd, catNomina.xsd).

Version 9.1 of FirmaSAT (2018-10-25):

* Added support for new hidrocarburos complementos `IngresosHidrocarburos` and `GastosHidrocarburos10` required from 1 November 2018
* Added support for revised `catNomina` catalog issued 8 October 2018

Version 9.0.2 of FirmaSAT (2018-08-31):

* Fixed issue where an Impuestos element included in Addenda causes an error.

Version 9.0.1 of FirmaSAT (2018-07-10):

* Fix for obscure error in order of TotalAllowanceCharge element in detallista complemento.

Version 9.0 of FirmaSAT (2018-06-25):

* Added XML validation checks against "huge" XSD catalog files. See [Checks against XSD catalogs](#checkcatalogs).
* Added many internal improvements for XML validation.
* Fixed Impuestos element order detection problem in CFDI v3.3.
* Added support for the following:

    + Estado de Cuenta Combustible versión 1.2 (ecc12)
        + Consumo de combustibles versión 1.1 (consumodecombustibles11)
        + Controles Volumétricos para Gasolina o Diesel versión 1.2 (controlesvolumetricos)
* Added diagnostic [SAT_Comments](diFirmaSat2_h_Ref.html#ac2bdaa2ae237a4737857a565b0507fa0) function.

Version 8.2 of FirmaSAT (2017-12-10):

* Improved [Get XML Attribute](#GetXMLAttribute) to use a simplified [Xpath expression](#xpathexpression) to select elements in the more complicated structure of CFDiv3.3 XML documents.
For example, 
    > ```

    > /Comprobante/Conceptos/Concepto/Impuestos/Retenciones/Retencion
        > /Comprobante/Impuestos/Retenciones/Retencion
        > //Concepto[2]//Retencion[3]

    > ```

* Added the [NewKeyFile](#SaveKeyFile) function to save an existing private key file with a new password.
* Added the .NET methods `Sat.XmlNoMatch` and `Sat.SetXmlNoMatch` to allow changes to the default `!NO MATCH!` result
when an element is not found.
* Rationalized the [error codes](#errorcodes) returned by the FirmaSAT functions. 
In particular, an XML document with a bad version number will now cause a `NOT_SUPPORTED_ERROR` instead of the misleading `NO_MATCH_ERROR`.
* Added "include" files to the distribution which enumerate the error codes: see the files 
**errorcodes-fsa.h**, 
**errorcodes-fsa.bas**, 
**errorcodes-fsa.vb**, and 
**errorcodes-fsa.cs**. 
You may optionally include these files in your projects if you find them useful.
* Added option in the install program to add the command-line `FirmaSAT.exe` to the environment PATH variable, so it will always work in the command-line console.
* Fixed XMLOK/ValidateXML issues with

    + c_TipoRelacion values as per changes made to catCFDI.xsd by SAT on 29/11/2017
        + notariospublicos:DatosOperacion/@NumInstrumentoNotarial now allows up to 999999
        + cce11:Domicilio/@Incoterm
        + Concepto element with more than 2 children
* Fixed XMLOK/ValidateXML to catch an element which has content but must be empty, see [XML restriction violated: Element must be empty](#mustbeempty).
* Validation errors now give the line number of the offending item.
* Updated tests to use latest test signing keys from SAT (expiring May 2021).

Version 8.1.3 of FirmaSAT (2017-08-23):

* More minor fixes to XMLOK/ValidateXml:

    + Fixed nomina12:Receptor/@RiesgoPuesta to accept "99" as added to catNomina.xsd by SAT.
        + Fixed cce11:Domicilio/@Estado to accept 2-letter state codes.

Version 8.1.2 of FirmaSAT (2017-08-18):

* Updated XMLOK to reflect changes in `catCFDI.xsd` as updated by SAT 12 August 2017.

    + Added TipoRelacion="07".
        + Removed MetadoPago="PIP".
        + Allow ClaveUnidad with lower-case letters (such as "Xyv"!!).
        + All other changes do not affect FirmaSAT.
        + We *do not* expect these changes to be final!
* Fixed error with leyandasFisc complemento in CFDIv3.3.
* Changed behaviour of `Sat.GetXmlAttribute` to return "!NO MATCH!" if element not found instead of empty string.

Version 8.1 of FirmaSAT (2017-06-08):

* Updated support for Anexo 20 Versión 3.3 (CFDi v3.3) 
and Complemento para recepción de Pagos (`Pagos10`)
as per latest SAT specifications.

    + TotalImpuestos issue in Secuencia de Elementos a Integrar en la Cadena Original 
        with Pagos10 has been corrected to match latest `Pagos10.pdf` issued 31 May 2017

        + Changed XMLOK to reflect changes in `cfdv33.xsd` issued 19 May 2017.
* Added support for Contabilidad electrónica v1.3.

Version 8.0.1 of FirmaSAT (2017-05-10):

* Fixed error with `Impuestos` element in cadena original.

Version 8.0 of FirmaSAT (2017-05-02):

* Added (provisional) support for Anexo 20 Versión 3.3 (CFDi v3.3) 
and complemento `Pagos10` (Complemento para recepción de Pagos).
* Changed default behaviour for [SignXML](#SignXML) and  [MakeDigest](#MakeDigest) 
 to use the appropriate digest algorithm according to the XML version. 
That is, it will automatically use SHA-1 for a CFD v3.2 document and SHA-256 for CFD v3.3.
* Added [Asciify](#AsciifyXmlDocument) functions which will replace all non-ASCII characters with XML character references. 
The output string contains only US-ASCII characters and can safely be used as input to other functions without concern for character encoding issues.
* Added [InsertCert](#InsertCertificateDetails) functions which can be used to complete the `Certificado` and `NoCertificado`
nodes before computing the digest or signing the document.
* Improved support for running FirmaSAT in multiple threads.

Version 7.4.4 of FirmaSAT  (2017-03-26):

* Minor fix to to remove MD5 options from FirmaSAT.exe command-line program.

Version 7.4.2 of FirmaSAT  (2017-02-19):

* Added fixes for changes to `nomina12.xsd`
(Requisitos de los recibos de nómina)
and associated catalog XSD files modified by SAT January 2017.
* Improved GetXmlAttribute
to accept non-ASCII Latin-1 characters in attribute name, e.g. "Año"

    ```
    > FirmaSAT ATTRIBUTE -e nomina12:CompensacionSaldosAFavor -a Año nomina12prueba-base.xml
    2016

    ```

* Fixed obscure empty element issue with detallista documents and BIGFILE option.
* Fixed minor XML parsing issue for `totalDigits` facet in decimal types.

Version 7.4 of FirmaSAT  (2016-11-21):

* Added support for new Complementos issued by SAT October 2016:

    + `nomina12.xsd`
        		(Requisitos de los recibos de nómina)

        + `ComercioExterior11.xsd`
        	(Comercio Exterior)

Version 7.3.10 of FirmaSAT  (2016-07-29):

* Added support for new Complemento issued July 2016:

    + `ine11.xsd`
        		(INE)

* Fixed issue where 32-bit programs would not work on old CPUs without SSE2 support.
* Removed support for MD5 digests and signatures (not relevant since 2010).

Version 7.3 of FirmaSAT  (2016-03-19):

* Added support for new Complementos issued March 2016:

    + `ComercioExterior10.xsd`
        	(Comercio Exterior)

        + `ine10.xsd`
        		(INE)

Version 7.2.3 of FirmaSAT  (2016-01-23):

* Fixed minor compatability issues with empty attributes and missing "optional-but-required" detallista elements.
* Minimum required operating system is now Windows XP-SP2 and above (that is, XP/Vista/W7/W8/W10). Legacy support for W98/NT4/2000 removed.

Version 7.2.1 of FirmaSAT  (2015-11-02):

* Added support for new Complementos and ComplementosConcepto:

    + `AcreditamientoIEPS.xsd`
        	(Acreditación del IEPS)

        + `ecc11.xsd`
        	(Estado de Cuenta de Combustibles)

* Fixed minor XML parsing issue for decimal type with `fractionDigits` restriction and excess trailing zeros.

Version 7.2 of FirmaSAT  (2015-08-12):

* Added support for Complemento `obrasarteantiguedades.xsd` 
	(Obras de Artes Plásticas y Antigüedades)
* Added extra options to [QUERYCERT](#querycert) functions to extract length of key and signature algorithm from 
'Certificado' field or X.509 certificate file.
* Improved processing speed for 2048-bit signatures.
* Fixed XML parsing error for zero-length codigoPostal attribute.
* Updated test files.

Version 7.1 of FirmaSAT  (2015-07-02):

* Added support for new Complementos:

    + `servicioparcialconstruccion.xsd`
        	(Servicios parciales de construcción)

        + `renovacionysustitucionvehiculos.xsd`
        		(Renovación y sustitución de vehículo)

        + `certificadodedestruccion.xsd`
        		(Certificado de destrucción)

Version 7.0 of FirmaSAT  (2015-01-12):

* Added support for Contabilidad documents 
(Contabilidad en medios electrónicos).
* Added support for Controles volumétricos documents 
(del Archivo XML de Controles Volumétricos para Gasolina o Diesel).
* Added a ["BIGFILE" option](#bigfileoption) to speed up the signing of large XML documents.

Version 6.0 of FirmaSAT  (2014-12-19):

* Added support for Retenciones documents 
(Retenciones e información de pagos)
with specification `retencionpagov1.xsd`.
* The
`[SAT_XmlReceiptVersion](diFirmaSat2_h_Ref.html#ade3d50c17b34fc45c966badf64952297)` function and 
`[Sat.XmlReceiptVersion](fsaDotNetManual.html#M_Sat_XmlReceiptVersion)` method 
returns 1010 for a Retenciones version 1.0 document.
* Improved HELP in `FirmaSAT.exe`.
* Added features to 
`[SAT_GetXmlAttributeEx](diFirmaSat2_h_Ref.html#aa046bd111fdb13b02fbbe47856aafde2)` function and 
`[Sat.GetXmlAttribute](fsaDotNetManual.html#M_Sat_GetXmlAttribute)` method 
to return values of attributes in root element and name of root element itself.

Version 5.4.0 of FirmaSAT  (2014-05-18):

* Added support for Complemento NotariosPublicos `notariospublicos.xsd`
* Added `[SAT_Uuid](diFirmaSat2_h_Ref.html#a60f6a8a30ab85abf5e33696c6374aaa2)` function and 
`[Sat.Uuid](fsaDotNetManual.html#M_Sat_Uuid)` method 
to generate a Universally Unique IDentifier (UUID) compliant with RFC 4122.
* Added option `SAT_TFD` to the `[SAT_SignXml](diFirmaSat2_h_Ref.html#a36090ace5c7554beb0f2e49b329c6505)` function and 
added the `[Tfd.AddSignedTfd](#M_Tfd_AddSignedTfd)` method
to create and insert a `tfd:TimbreFiscalDigital` element signed by a PAC's key/certificate pair.
* Fixed signature/cadena error if Impuestos element had `totalImpuestosTrasladados="0.00"` but no matching Traslados element.
* Fixed overflow problem with very long error messages.

Version 5.3.0 of FirmaSAT  (2014-01-27):

* Added options to output empty elements using single empty element tags `<foo/>` instead of default
two-tag form `<foo></foo>`.
* Added `[SAT_SignXmlToString](diFirmaSat2_h_Ref.html#a225f0e13640a227f301cfd22b755f220)` function and 
`[Sat.SignXmlToBytes](fsaDotNetManual.html#M_Sat_SignXmlToBytes)` method 
to output signed XML data to memory instead of to a file.
* Replaced `FileFormatOpt` in `Sat.SignXml` method with
`SignOptions` in new `[Sat.SignXmlEx](fsaDotNetManual.html#M_Sat_SignXmlEx)` method.
The `FileFormatOpt` option introduced in v5.2 is now obsolete (sorry).
* Deprecated use of `HashAlgorithm` parameter with `Sat.SignXml` method.
* Added options to output encrypted private key as a PEM string (which can be used as input for `szKeyFile` parameter).
See [Get Private Key as a String](#GetPrivateKeyAsAString).
* Removed use of temporary files when signing XML documents (a possible source of crashes on some systems)
* Added `SAT_GetAttributeEx` function with option to encode output in Latin-1 instead of UTF-8.
* Added feature to pass XML data as a string in the `szXmlFile` parameter.

Version 5.2.2 of FirmaSAT  (2014-01-04):

* Added support for Complemento Concepto VentaVehiculos `ventavehiculos11.xsd`

Version 5.2.1 of FirmaSAT  (2013-12-29):

* Updated to reflect latest revisions to `nomina11.xsd` as changed by SAT on 18 December 2013.
* Added support for Complemento CFDI Registro Fiscal `cfdiregistrofiscal.xsd`

Changes in FirmaSAT version 5.2.0  (2013-12-13):

* Added support for 2014 payroll supplements as specified in `nomina11.xsd`.
* Added option *not* to include a UTF-8 byte-order mark (BOM) in the output when signing an XML file.
* Removed obsolete `DATENOTAFTER` action in command-line. 
Use [QUERYCERT Command](#Cmd_QUERYCERT) instead.
* Version number is now five digits (50200) instead of three (514).

Changes in FirmaSAT version 5.1.2a  (2012-09-25):

* Updated this manual to reflect latest changes in 2012 
	and to make consistent with `diFirmaSat2_h_Ref.html` and `FirmaSat.NET.chm` documents.
* Changed the tests in `DoTests.bat` and other programming test files to use the
	latest test certificates issued by SAT with test XML documents dated after 1 July 2012.
* Minor update to the FirmaSAT.exe command-line
	utility to fix occasional problem displaying Windows OEM characters with `-w` option.

Changes in FirmaSAT version 5.1.2  (2012-07-14):

* Minor update with fix for error when running `XMLOK` or `SAT_ValidateXml` check on
an XML file containing a Complemento Concepto VentaVehiculos element.

Changes in FirmaSAT version 5.1.1  (2012-05-11):

* Minor update with fix for `Comprobante/@SerieFolioFiscalOrig` node in CFDi version 3.2, 
	required in cadena original but 
	erronously omitted in preliminary regulations issued by SAT.

Changes in FirmaSAT version 5.1.0  (2012-03-23):

* By popular request we have added a new function to [create a PFX file](#writepfxfile) in the base64 file format 
required by some PAC's to cancel a CFDi invoice. 
You can seal this PFX/PKCS-12 file with the password of your choice.
* Added a new function to [query an X.509 certificate](#querycert) for a given value. 
The available queries include a search for the subject's RFC number and the issuer's organization name 
(which should always be "Servicio de Administración Tributaria") if the certificate was issued by SAT.
* Fixed XML type check for the number of decimal places in the version 2.0 t_Importe element (thanks, Alonso).
It was only 2 decimal places in the original SAT schema, but 6 are now allowed.
* Added more error messages in Spanish. Removed accented characters from the Spanish help and error messages 
(á→a,é→e,...). 
This makes them display properly in all environments.
* Changed the behaviour of the [command-line utility](#commandlineutility)
so the output file must be explicitly specified with the "-o" option. 
See [The behaviour of the FirmaSAT command-line has changed in version 5.1](#outputfilewarning).
This reduces the likelihood of existing data files getting accidentally overwritten by the output.

Changes in FirmaSAT version 5.0.1  (2012-01-07):

* Minor update to fix bug with missing Emisor/@Nombre node for cadena original in new versions 2.2 and 3.2.

Changes in FirmaSAT version 5.0.0 (2011-12-29):

* Added support for CFD versión 2.2 and CFDi versión 3.2 documents. 
	These are automatically detected from
	the Comprobante/@version attribute in the input XML file.

* Added support for the new supplements (complementos) introduced in 2011 and 2012:

    + iedu.xsd
        + psgcfdsp.xsd
        + ventavehiculos.xsd
        + pfic.xsd
        + TuristaPasajeroExtranjero.xsd
        + leyendasFisc.xsd
        + donat11.xsd
        + terceros11.xsd
* Introduced stricter XML data type and length checking when 
	[validating an XML document](#ValidateXMLDocument).

* Added the [`SAT_GetKeyAsString`](diFirmaSat2_h_Ref.html#aa517f7c0cbf0fedf5a785abe8ceeea1b) function,
the [`Sat.GetKeyAsString Method`](fsaDotNetManual.html#M_Sat_GetKeyAsString_StringString),
and the [`GETKEYSTRING`](#Cmd_GETKEYSTRING) command.
These will form the private key from the encrypted private key file in the required base64 format 
to insert in the `llaveCertificado` element of a `Cancelacion` XML document.
* Added the notation `elementname[N]` to specify the N'th element with name `elementname` in the document
when using the [`SAT_GetXmlAttributeEx`](diFirmaSat2_h_Ref.html#aa046bd111fdb13b02fbbe47856aafde2) function,
the [`Sat.GetXmlAttribute Method`](fsaDotNetManual.html#M_Sat_GetXmlAttribute),
or the [`ATTRIBUTE`](#Cmd_ATTRIBUTE) command.
* Fixed issue with very rare 127-byte signature.

Changes in FirmaSAT version 4.1.0 (2011-07-14):

* XML files created by the [SignXML](#SignXML) functions will now include the
UTF-8 byte order mark (BOM) which is required by the SAT validator sites from July 2011.
* Added the [`SAT_FixBOM`](diFirmaSat2_h_Ref.html#ae9372d1895bf7583bb16ed0257c07e17) function,
the [`Sat.FixBom Method`](fsaDotNetManual.html#M_Sat_FixBom),
and the [`UTF8FIX`](#Cmd_UTF8FIX) command.
These will add the UTF-8 BOM to any existing file, if it does not already have it,
provided the file only contains valid UTF-8-encoded characters.

Changes in FirmaSAT version 4.0.0 (2011-07-05):

* Removed dependency on CryptoSys PKI. 
The file `diCrPKI.dll` is no longer required.
* Added functions and methods to operate on the [Timbre Fiscal Digital (TFD) element](#tfdelement).
Users can form the *cadena original del timbre fiscal digital del SAT*,
extract the digest from the signature, and verify the *selloSAT* signature.
* Fixed XML reader to cope with default namespace and unprefixed element names in versión 3.0 CFDi documents.

Changes in FirmaSAT version 3.0.0 (2010-12-23):

* Changed default message digest algorithm from MD5 to SHA-1.
* Added support for SAT version 3.0 CFDI XML files as per schema `cfdv3.xsd`. 
All functions automatically check the XML document for the Comprobante version number (2.0 or 3.0) 
and process accordingly.
* Added support for for all existing supplements as listed on 
		*Complementos de Factura Electrónica*
		as at 30 November 2010.

    + Proveedor de Servicios Autorizado (`psgecfd.xsd`)
        + Estado de cuenta de combustibles de monederos electrónicos como Factura Electrónica (`ecc.xsd`)
        + Donativos "Donatarias" (`donat.xsd`)
        + Compra venta de "Divisas" (`Divisas.xsd`)
        + Estados de Cuenta Bancario "ECB" (`ecb.xsd`)
        + Impuestos Locales (`implocal.xsd`)
        + Emisión por cuenta de terceros (`terceros.xsd`)
        + Sector de ventas al detalle ("Detallista") (`detallista.xsd`). 
        				Detallista was already included in version 2, but it now copes with detallista together with psgecfd.

* Added [Get XML Receipt Version Number](#getxmlreceiptversion) to find the Comprobante version number (2 or 3) of an XML document.
* Added [Check Key and Certificate](#checkkeyandcert) to check whether a private key matches the public key in a certificate.
* Added alternative to [`SAT_GetCertExpiry`](diFirmaSat2_h_Ref.html#a7a7f455852ada5242dad620ad59e777f) and 
new method [`Sat.GetCertExpiry Method`](fsaDotNetManual.html#M_Sat_GetCertExpiry) 
to return the start date of a certificate.

<a id="index"></a>Index
-----------------------

| [Adding a TFD element](#addtfd) [Asciify an XML Document](#AsciifyXmlDocument) [BIGFILE option](#bigfileoption) [C# programming](#csharpprogramming) [C++ (STL) Programming](#cppprogramming) [C/C++ Programming](#cplusplusprogramming) [Changes in older versions](#changesinolder) [Changes in this version](#changesinthis) [Check Key and Certificate](#checkkeyandcert) [Checks against XSD catalog files](#checkcatalogs) [Command-line utility](#commandlineutility) [Diagnostic Procedures](#diagnosticprocs) [Error Codes](#errorcodes) [Error-related procedures](#errorprocs) [Example batch file](#batchfile) | [Extract Digest From Signature](#ExtractDigestFromSignature) [Fix UTF-8 BOM](#fixutf8bom) [Generate a UUID](#generateuuid) [Get Certificate as a String](#GetCertificateAsAString) [Get Certificate Serial Number](#GetCertificateSerialNumber) [Get Certificate Validity Dates](#GetCertificateValidityDates) [Get Private Key as a String](#GetPrivateKeyAsAString) [Get XML Attribute](#GetXMLAttribute) [Get XML Receipt Version Number](#getxmlreceiptversion) [Index](#index) [Insert Certificate Details](#InsertCertificateDetails) [Introduction](#introduction) [LIBINFO Command](#Cmd_LIBINFO) [Make a PFX File](#writepfxfile) [Make Digest](#MakeDigest) | [Make Pipe String](#MakePipeString) [Make Signature](#MakeSignature) [Notes on CFD v3.3 and v4.0](#notesoncfdv33) [Pre-dimensioning szOut](#predimensioningszout) [Query a Certificate](#querycert) [Revision History](#Revisions) [Save key file with a new password](#SaveKeyFile) [Sign XML](#SignXML) [Simplified XPath expressions for the elementName parameter](#xpathexpression) [Timbre Fiscal Digital (TFD) element](#tfdelement) [Validate XML Document](#ValidateXMLDocument) [`VB.NET`/VB2010+ programming](#vbnetprogramming) [VB6/VBA Programming](#vb6programming) [Verify XML Signature](#VerifyXMLSignature) [XML restriction violated: Element must be empty](#mustbeempty) |
| --- | --- | --- |

<a id="Revisions"></a>Revision History
--------------------------------------

September 2025: Update for markdown  

April 2024: Update for Version 10.70  

12 March 2022: Update for Version 10.50  

17 December 2021: Update for Version 10.40  

8 September 2021: Update for Version 10.0  

8 May 2021: Update for Version 9.3  

6 August 2020: Update for Version 9.2  

25 October 2018: Update for Version 9.1  

25 June 2018: Update for Version 9.0  

12 December 2017: Update for Version 8.2  

8 June 2017: Update for Version 8.1  

2 May 2017: Update for Version 8.0  

14 January 2017: Minor editorial changes.  

21 November 2016: Update for Version 7.4  

19 March 2016: Update for Version 7.3  

15 August 2015: Update for Version 7.2  

12 January 2015: Update for Version 7.0  

19 December 2014: Update for Version 6.0  

18 May 2014: Update for Version 5.4  

27 January 2014: Update for version 5.3.  

29 December 2013: Minor update for version 5.2.1.  

13 December 2013: Update for version 5.2.  

25 September 2012: Minor update for version 5.1.2a.  

23 March 2012: Update for version 5.1.  

29 December 2011: Update for version 5.0.  

5 July 2011: Update for version 4.0.  

21 December 2010: Version 3.0 manual first published by DI Management Services Pty Limited.  

7 August 2007: Version 1.0 of FirmaSAT released.

---

Copyright © 2007-25 D.I. Management Services Pty Limited t/a CryptoSys ABN 78 083 210 584, Australia.
All rights reserved.  

<[https://di-mgt.com.au](https://di-mgt.com.au "External link")>
<[https://cryptosys.net](https://cryptosys.net "External link")>

---

