CryptoSys Home > PKI > How to create a SAT Cancelacion document

How to create a SAT Cancelación document using CryptoSys PKI Pro and SC14N


NewUpdated 2022-01-29. Completely re-written for the 2022 CFDI versión 4.0 specification.

Example | Avoid XML-DSIG whitespace hassles | Source code to do this | Procedure | Passing key and certificate data as a string | How can we verify the signature? | Downloads | Required libraries | Contact

We show here how to create a CancelaCfdi XML document (Esquema cancelación CFDI versión 4.0) as per Actualización Factura electrónica - Reforma Fiscal 2022, digitally signed using XML-DSIG.

Example

Here is an example, reformatted for display purposes (see output as a "flattened" one-line string).

<?xml version="1.0" encoding="utf-8"?>
<CancelaCFD xmlns="http://cancelacfd.sat.gob.mx">
  <Cancelacion xsi:schemaLocation="http://cancelacfd.sat.gob.mx CancelaCfdi.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  Fecha="2022-01-29T15:45:12" RfcEmisor="AAA010101AAA">
    <Folios>
      <Folio UUID="E3BA5811-FD07-4B9C-84B4-B146D7560575" Motivo="01" 
      FolioSustitucion="20D816A0-BA64-4DF4-BE87-AA55E62F992F" />
    </Folios>
    <Folios>
      <Folio UUID="29880559-5057-4871-9572-A222FD10BD97" Motivo="02" />
    </Folios>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
        <Reference URI="">
          <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          </Transforms>
          <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
          <DigestValue>YzhhA9+z+QYh9CTaYZ3CBegpdNg=</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>
      QhrwPqmk0mbva9fPEcubk877qqXYrE0jFg0JROWFKK74mZHfpPp5MVBbL3CPf4z3LeSC4HZbN2ZRfBJ13Rstu47BVK4A7R+W4GsOC8q+Xg2Et4f80p
      HUSlKTt03uzorhvelVQbFGAgK0VQBldj80oSLH7UFs7VJCSLlb+CVjpQpBq93PFkU40/Aywf/LhoTT3Cy//FUkjxywyfMGJAmPxb45oewJGNgADH4m
      GBREUIp0WJtNBCYUxBEEt1J42hk4VkIT0Zid7kxIKoE9wB77uMZiBiu1Ry8iTBuJ7Ni9DYnHPeptw0/RgH2cBls0+i24XsIL5xzZYWMXZ7I91DsYMg==
      </SignatureValue>
      <KeyInfo>
        <!-- /CUT/ -->
      </KeyInfo>
    </Signature>
  </Cancelacion>
</CancelaCFD>

Avoid XML-DSIG whitespace hassles: output as a "flattened" one-line string

There are issues with XML-DSIG in dealing with the white space between elements (indentations, tabs vs spaces, trailing white space, etc) which may get changed during transmission and invalidate the signature.

We avoid these hassles by removing it all. We "flatten" the input document before signing. That is, we create the signed output XML document in one long line with no white space between elements. This makes subsequent signature validations less prone to error, but makes the display less friendly.

<?xml version="1.0" encoding="utf-8"?><CancelaCFD xmlns="http://cancelacfd.sat.gob.mx"><Cancelacion xsi:schemaLocation="http://cancelacfd.sat.gob.mx CancelaCfdi.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Fecha="2022-01-29T15:45:12" RfcEmisor="AAA010101AAA"><Folios><Folio UUID="E3BA5811-FD07-4B9C-84B4-B146D7560575" Motivo="01" FolioSustitucion="20D816A0-BA64-4DF4-BE87-AA55E62F992F" /></Folios><!-- /CUT/ --></Cancelacion></CancelaCFD>

Note that if you add back any whitespace by, say, pretty-printing, the signature will be invalid.

Source code to do this

C# code: SignEnvelopedSignature.cs. See Downloads below for the full set of source code, base XML template and test files; and Required Libraries.

Procedure

1. Customize the base template file cancelacion-2022-base.xml with your own data in the elements shaded green. You can have up to 10,000 <Folios> elements. The <Signature> element should be copied exactly as is.
<?xml version="1.0" encoding="UTF-8"?>
<CancelaCFD xmlns="http://cancelacfd.sat.gob.mx">
    <Cancelacion 
        xsi:schemaLocation="http://cancelacfd.sat.gob.mx CancelaCfdi.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        Fecha="@!TIMESTAMP!@" RfcEmisor="AA010101AAA">
        <Folios>
            <Folio UUID="E3BA5811-FD07-4B9C-84B4-B146D7560575" Motivo="01"
                FolioSustitucion="20D816A0-BA64-4DF4-BE87-AA55E62F992F"/>
        </Folios>
        <Folios>
            <Folio UUID="29880559-5057-4871-9572-A222FD10BD97" Motivo="02"/>
        </Folios>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
                <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
                <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <Reference URI="">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <DigestValue>@!DIGVAL!@</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>@!SIGVAL!@</SignatureValue>
            <KeyInfo>
                <KeyValue>@!RSAKEYVALUE!@</KeyValue>
                <X509Data>
                    <X509IssuerSerial>
                        <X509IssuerName>@!ISSUERNAME!@</X509IssuerName>
                        <X509SerialNumber>@!SERIALNUMBER!@</X509SerialNumber>
                    </X509IssuerSerial>
                    <X509Certificate>@!CERTIFICATE!@</X509Certificate>
                </X509Data>
            </KeyInfo>
        </Signature>
    </Cancelacion>
</CancelaCFD>
Any white space between elements will be removed before processing, so any indentation is not important. The placeholders in the document in the form @!...!@ will be replaced by valid values. The "@!TIMESTAMP!@" placeholder will be replaced by the local system clock time in the correct ISO time format. If you want to hardcode a time there yourself, just overwrite it in the base file. The placeholders "@!DIGVAL!@" and "@!SIGVAL!@" are mandatory.
2. Run the method SignEnvelopedSignature.SignDoc
static string SignDoc(string outputxmlFile, string baseXmlFile, string certFile, string keyFile, string password, bool noFlatten = false)

The input parameters for SignEnvelopedSignature.SignDoc are:

outputxmlFile
Name of signed output file to be created.
baseXmlFile
Path to base XML document.
certFile
Filename of X.509 certificate file, or certificate-as-a-string.
keyFile
Filename of matching private key (or PEM string).
password
Password for private key file ("" if unencrypted).
noFlatten
Set as true to leave XML in original format (default=flatten to a single line).
If the program runs successfully, the output file specified in outputxmlFile will be created.

There are more notes on usage in the source code itself.

Example

signedDoc = SignDoc("cancelacion-2022-signed.xml", "cancelacion-2022-base.xml", "emisor2021.cer", "emisor.key", password:"12345678a", noFlatten:false);

Output

The final document (in one line) (zipped form 3 kB). Here is a reformatted pretty-print version, which displays nicely but will not validate because of its extra whitespace characters (hey, don't blame us, we didn't design XML-DSIG!).

Passing key and certificate data as a string

You can avoid using files completely for the private key and certificate. Instead of passing the filenames as arguments for the keyFile and certFile parameters, you can pass the data directly as a string. See
KeyCertsAsStrings.cs.
Note that the certificate and key in this code are different from the latest test examples in the download.

How can we verify the signature?

Obviously you can verify this by submitting to SAT. If you have problems, please let us know with the error message you're getting. Please send us an example of your signed XML file that fails (ask us first, we'll get back to you on how to send it).

As an independent alternative, you can verify the signature using the Online XML Digital Signature Verifer. This will verify that the XML-DSIG signature is correct, but is not necessarily proof that the document satisfies all the SAT requirements. However, if it fails, something definitely needs to be fixed.

New2022-03-20: See Troubleshooting problems on the 'Online XML Digital Signature Verifier' site

  1. Open the final XML file cancelacion-2022-signed.xml in a text editor (that's the one-line version, not the pretty-printed one).
  2. Select all
  3. Copy and paste into the text box on the Verifier page
  4. Click Verify Signature

Online XML Digital Signature Verifer

The result:

RESULT: Signature is OK

Downloads

Download the source code, test files and base XML template: SignEnvelopedSignature.cs.src.zip (19.9 kB).
SignEnvelopedSignature.cs.src
|   SignEnvelopedSignature.cs
|   SignEnvelopedSignature.csproj
|
+---Properties
|       AssemblyInfo.cs
|
\---Work
        CancelaCfdi.xsd
        cancelacion-2022-base.xml
        cancelacion-2022-signed-pretty.xml
        cancelacion-2022-signed.xml
        emisor.key
        emisor2021.cer

Required libraries

The code requires the following libraries to be installed on your system. Available from https://www.cryptosys.net/.
  1. CryptoSys PKI Pro: https://www.cryptosys.net/pki/
  2. SC14N, a straightforward XML canonicalization utility: https://www.cryptosys.net/sc14n/
Free trial versions are available for testing at the above links. If you purchase SC14N at the same time as CryptoSys PKI, you can save US$40.
When ordering CryptoSys PKI Pro on the DI Management Services Store, check the "Add to Order" box for SC14N.
Add to Order to save money

Contact

For more information or to comment on this page, please send us a message.

This page first published 1 October 2012. Last updated 15 November 2022.