Problems with ZATCA XML Signatures, Invoice Hash, and QR

Chilkat is trying to help various customers with signing XML invoices (XML Digital Signatures) to produce valid signed XML for Saudi ZATCA.   I’m sorry to say that so far it is not successful.  The reason is that the ZATCA SDK Toolkit produces obviously invalid results.

In addition, the documentation has many errors and is not accurate.

Let’s begin with installation instructions.  Trying to install on Windows was a complete failure, so we moved to Linux.

ZATCA Install Problems on Ubuntu 20.04.4 LTS (Focal Fossa)

To install, don’t follow the ZATCA SDK ToolKit User Manual,  because it’s entirely incorrect.  Follow these instructions instead.

on Ubuntu 20.04.4 LTS (Focal Fossa), with JDK 11 installed.

Install jq if not installed.

sudo apt install -y jq

Unzip (assuming you know how to download the .zip)

Move to the zatca-envoice-sdk-203 directory and run the install.sh

Note: The command is not “fatoorah”, it is “fatoora”!!!

Try running “fatoora -h”

OK, where is global.json?  Why was it not found?  There is a global.json in the Apps directory, so let’s move it up one level..

OK, now the .jar file cannot be found.  Move it up one directory level..

OK… I was mistaken, “-h” does not provide the syntax help we were looking for, it is “-help”

 


Now that we have it “installed”, let’s try to do something.
Let’s first try the -generateHash flag to generate a hash for an XML invoice.

Copy a sample invoice.xml into your directory and then try the following:

At this point, I write code using Chilkat to sign the XML, as shown at https://www.example-code.com/csharp/zatca_e-invoicing_xml_signature.asp and the hash contained in the signed XML is the same as the generated hash using the ZATCA tool.

OK, things are looking good!  Now let’s try using the ZATCA tool to sign the XML to see what it produces, and then let’s use Chilkat to verify the XML signature as a litmus test..

OK… more problems!

I found these config files:  global.json, config.json, and defaults.json

Here’s the contents of mine, after making changes, to get the fatoora -sign command to work:

Now let’s try fatoora -sign again…

OK, so let’s look at the signed XML produced by the fatoora tool…

Let’s look at the DigestValues within the SignedInfo:

The 1st digest value, XyHXO1tzajvgoL5vIoAZvPB1pjWGFnd09K5UB3PbyTk=, looks good.  It’s the value  also created by Chilkat when signing, and it’s also the value created using fatoora -generateHash

However, the 2nd DigestValue is obviously NOT correct!

It should be a sha256 hash, and should be the same length as the previous DigestValue.  It seems to be twice as long. Let’s decode the base64 to see what we have.  I want to re-encode from base64 to hex.  I can do it using Chilkat’s online tool here:   https://tools.chilkat.io/reencode

The hex representation of  ZWIzMjVmZDg1ZWI3NTZkMGM3Zjg4NDU3Y2I0M2NjZTgxZmJhZTAxZDYwNmJjMzhmNTcyZTc0OGE0NGQzYzA3Zg==
is 65623332356664383565623735366430633766383834353763623433636365383166626165303164363036626333386635373265373438613434643363303766

Well.. that’s strange because those hex values are all us-ascii.  Let decode from hex using the tool at https://tools.chilkat.io/decoding

Decoded from hex, we get these us-ascii chars:  eb325fd85eb756d0c7f88457cb43cce81fbae01d606bc38f572e748a44d3c07f

And eb325fd85eb756d0c7f88457cb43cce81fbae01d606bc38f572e748a44d3c07f looks like hex, so what if we re-encode from hex to base64?

eb325fd85eb756d0c7f88457cb43cce81fbae01d606bc38f572e748a44d3c07f in base64 representation becomes 6zJf2F63VtDH+IRXy0PM6B+64B1ga8OPVy50ikTTwH8=

But 6zJf2F63VtDH+IRXy0PM6B+64B1ga8OPVy50ikTTwH8= does not match what Chilkat produced for the DigestValue of the signed properties.  I trust Chilkat’s value.  The value produced by fatoora is obviously incorrect because it is twice a long as what a SHA256 hash should be.

The fatoora SDK Tool also Produces an Invalid CertDigest

It is also twice as long as it should be, just like the 2nd Digest Value in the SignedInfo.

The SHA256 hash of a certificate is simply the SHA256 hash of the binary DER encoding of the certificate.  With 100% certainty, Chilkat can compute the correct SHA256 hash of the DER of a certificate.  Even if we try to transform the twice-as-long SHA256 hash produced by fatoora, it is NOT the correct SHA256 hash for the certificate.

In Summary, the Fatoora SDK Tool Does not Work Correctly, and the documentation is poor and inaccurate.