What do Signed Properties Look Like When Hashing?

It turns out the spaces matter even in the version you are submitting to ZATCA’s servers, not just when hashing.

ZATCA’s servers are hashing the SignedProperties you submit via the API as-is, they do not transform them to the spacing format that is required before hashing. Thus if you do not use the same spaces you will always get a hashing error returned by the server, even if your hash is actually correct.

In our call I suggested one of 2 changes to make spaces not matter:

  1. As the original documentation used to say, canonicalize before hashing. This would require ZATCA to accept both the current and canonicalized format and may result in significant overhead and issues.
  2. On ZATCA’s serverside, simply transform any signed properties block that an API client sends to ZATCA to ensure it has the same spaces. This matches the way we hash invoices, both the client and server format the content in the same way (canonicalization) and then the hash is generated and compared. The problem right now is that ZATCA’s server does not format the SignedProperties and expects the client to do it, but this behavior is not documented. Following this suggestion should retain backwards-compatability and make spaces not matter.

tl;dr version
For now just ensure any step you are using the SignedProperties block in 100% match ZATCA’s samples in terms of whitespace.

@obahareth-mrsool Are youe solved this issue

Finally, I resolved this error by having 36 spaces in the first line and 4 spaces after that.

    $signaturePart = '<xades:SignedProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">' . PHP_EOL .

xades:SignedSignatureProperties’ . PHP_EOL .
xades:SigningTimeSIGNING_TIME_VALUE</xades:SigningTime>’ . PHP_EOL .
xades:SigningCertificate’ . PHP_EOL .
xades:Cert’ . PHP_EOL .
xades:CertDigest’ . PHP_EOL .
’ <ds:DigestMethod xmlns:ds=“XML-Signature Syntax and Processing” Algorithm=“XML Encryption Syntax and Processing”/>’ . PHP_EOL .
’ <ds:DigestValue xmlns:ds=“XML-Signature Syntax and Processing”>HASH_DIGEST_VALUE</ds:DigestValue>’ . PHP_EOL .
’ </xades:CertDigest>’ . PHP_EOL .
xades:IssuerSerial’ . PHP_EOL .
’ <ds:X509IssuerName xmlns:ds=“XML-Signature Syntax and Processing”>ISSUER_NAME</ds:X509IssuerName>’ . PHP_EOL .
’ <ds:X509SerialNumber xmlns:ds=“XML-Signature Syntax and Processing”>SERIAL_NUMBER</ds:X509SerialNumber>’ . PHP_EOL .
’ </xades:IssuerSerial>’ . PHP_EOL .
’ </xades:Cert>’ . PHP_EOL .
’ </xades:SigningCertificate>’ . PHP_EOL .
’ </xades:SignedSignatureProperties>’ . PHP_EOL .
’ </xades:SignedProperties>';

1 Like

@obahareth-mrsool @MAl-tamimi
I’m encountering an issue where the invoice generated through the SDK produces the correct signing invoice hash. However, when I attempt to manually generate the same signing hash, I’m unable to match it. Can someone please help me in this regard.

Dear @hamza-id

Thanks for reaching out,

Please find the attached (SigningProcessUpdated.pdf) for signing process manually ensure to follow all the steps.

Uploading: SigningProcessUpdated.pdf…

If you faced any issues do not hesitate to reach out our support team via below mail mentioning all the detailed concerns to provide comprehensive support as usual.

SP mail: sp_support@zatca.gov.sa

Thanks,
Ibrahem Daoud.

@idaoud The attached file cannot be downloaded. Seems your attachment did not go well.
Thanks

Dear @creativebusiness

Thanks for notifying,

Please find the attached:
SigningProcessUpdated.pdf (927.7 KB)

Thanks,
Ibrahem Daoud.