Unclarity in Signing Process

  1. There are OpenSSL commands for everything other than ECDSA signing. We tried doing it via OpenSSL ourselves, and via a number of other open source libraries and it says it’s invalid.
  2. In the signing process document, there are not enough example values like there are in the TLV docs.

Examples:
When it says “Hash the certificate”, what does that certificate look like? Is it with header blocks? Is it without the header blocks? I’ve also seen some cases where it is without header blocks and Base64-encoded.

When we say hex-to-base64 encoding. Do we mean like so:

  1. First step, generate a SHA256 digest:
    "\xBAx\x16\xBF\x8F\x01\xCF\xEAAA@\xDE]\xAE\"#\xB0\x03a\xA3\x96\x17z\x9C\xB4\x10\xFFa\xF2\x00\x15\xAD"

  2. Turn that digest into hex:
    "\xA1o\xF1\xFA\xAA\x0E\xDE#\x03\xA3g<@\xFA ]"

  3. Turn that hex into Base64:
    "oW/x+qoO3iMDo2c8QPogXQ=="

Or should we just skip step 2 and 3 and go straight to Base64 from the digest?

e.g.
"ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="

Or should we just get a hexdigest and Base64 encode it? (I was told by ZATCA we shouldn’t be using hexdigests anymore)

e.g.
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"

then Base64 encoding it
"YmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZA=="

We’ve tried all the approaches we mentioned here and all combinations of them and the validator/API are both still saying there are signing errors.

  1. There are OpenSSL commands for everything other than ECDSA signing. We tried doing it via OpenSSL ourselves, and via a number of other open source libraries and it says it’s invalid.
  2. In the signing process document, there are not enough example values like there are in the TLV docs.

Examples:
When it says “Hash the certificate”, what does that certificate look like? Is it with header blocks? Is it without the header blocks? I’ve also seen some cases where it is without header blocks and Base64-encoded.

When we say hex-to-base64 encoding. Do we mean like so:

  1. First step, generate a SHA256 digest:
    "\xBAx\x16\xBF\x8F\x01\xCF\xEAAA@\xDE]\xAE\"#\xB0\x03a\xA3\x96\x17z\x9C\xB4\x10\xFFa\xF2\x00\x15\xAD"

  2. Turn that digest into hex:
    "\xA1o\xF1\xFA\xAA\x0E\xDE#\x03\xA3g<@\xFA ]"

  3. Turn that hex into Base64:
    "oW/x+qoO3iMDo2c8QPogXQ=="

Or should we just skip step 2 and 3 and go straight to Base64 from the digest?

e.g.
"ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="

We’ve tried all the approaches we mentioned here and all combinations of them and the SDK is still saying there are signing errors.

The certificate mentioned in the signing process document is the X.509 certificate. Basically, you will follow the below steps to extract it correctly:

After completing CCSID API, it will return (binary security token), take this value, and decode it using base 64, the output is X509 certificate.

  1. Hash the x509 certificate (value from previous step) using SHA-256 (output). e.g.:69a95fc237b42714dc4457a33b94cc452fd9f110504c683c401144d9544894fb
  2. Encode the hashed x509 certificate using base64 (ASCII to base64) (output).
  3. e.g.:NjlhOTVmYzIzN2I0MjcxNGRjNDQ1N2EzM2I5NGNjNDUyZmQ5ZjExMDUwNGM2ODNjNDAxMTQ0ZDk1NDQ4OTRmYg==
  • The value inside the XML invoice should be the final output.

Notes:

1- The certificate should be without the header block, only the value of the certificate itself.
2- to encode values from (hex to base 64), example (hash of invoice), after hashing the invoice body using SHA-256A you should go straight forward to (hex to base64 encoder), encode the value of SHA256A the output will be the Hash of the Invoice.

Hey @MAl-tamimi,

For the certificate part that was very helpful, would you be able to provide sample values for the digest-to-base64 part as well? Or perhaps highlight which of the 3 processes I shared above is correct?

From what I can see in your example, you just generated a hexdigest and Base64-encoded it.

I’m a little confused because ZATCA told me I shouldn’t be using hexdigests.

Hey @MAl-tamimi,

For the certificate part that was very helpful, would you be able to provide sample values for the digest-to-base64 part as well? Or perhaps highlight which of the 3 processes I shared above is correct?

Yes, there is incorrect step in your process number 2, as you shouldn’t use the HEX in the invoice itself. Please follow the steps below:

After completing CCSID API, it will return (binary security token), take this value and decode it using base 64, the output is X509 certificate.

Hash the x509 certificate (value from previous step) using SHA-256 (output). e.g.:69a95fc237b42714dc4457a33b94cc452fd9f110504c683c401144d9544894fb

Encode the hashed x509 certificate using base64 (ASCII to base64) (output).
e.g.:NjlhOTVmYzIzN2I0MjcxNGRjNDQ1N2EzM2I5NGNjNDUyZmQ5ZjExMDUwNGM2ODNjNDAxMTQ0ZDk1NDQ4OTRmYg==