# Technical Assistance: Persistent "Invalid-CSR" Error in ZATCA Simulation Environment - Project AndalusSystem

**URL:** <https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740>\
**Category:** FATOORA portal and Simulation portal\
**Created:** [February 8, 2026, 3:38pm UTC](https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740 "2026-02-08T15:38:28Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![crumble](https://avatars.discourse-cdn.com/v4/letter/c/45deac/32.png) [@crumble](https://zatca1.discourse.group/u/crumble)\
**Post date:** [February 8, 2026, 3:38pm UTC](https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740/1 "2026-02-08T15:38:28Z")

</div>

**Dear Developer Team,**

I am currently developing a SaaS solution for laundries using **Django/Python**. To ensure full compliance with ZATCA’s Phase 2 requirements, we have built a dedicated **.NET 8.0 Security Bridge** to handle X509 certificate generation and digital signing, as Python has certain limitations with custom OIDs and ASN.1 encoding.

We are consistently hitting a **400 Bad Request: Invalid-CSR** error when attempting to obtain the Compliance CSID (CCSID) in the **Simulation Environment**. Despite following several recommendations from the Fatoora Developer Community regarding field order and spacing, the issue persists.

### 1. Our Technical Stack

- **Backend:** Python 3.14 / Django.

- **Security Bridge:**.NET 8.0 Web API (using `System.Security.Cryptography`).

- **Endpoint:** `https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation/compliance`

### 2. CSR Implementation Details

Our .NET bridge generates the CSR manually using `AsnWriter` to ensure strict DER encoding. Our current CSR structure includes:

- **Key Algorithm:** ECDSA (curve: `secp256k1`) with SHA256.

- **Subject Field Order:** We follow the SDK-mandated order: `CN` → `O` → `OU` → `C`.

- **Subject Attributes:** \* `CN`: Prefixed with `TST-` followed by the UUID.

- **Certificate Extensions:**

- **Formatting:** We have implemented a strict `.Trim()` on all inputs and ensured no unnecessary spaces exist around the `=` signs or within the RDN sequence.

### 3. Test Data Used

- **VAT Number:** `310122393500003` (Standard ZATCA Test VAT).

- **OTP:** `123456`.

- **Common Name Format:** `TST-886431145-310122393500003`.

### 4. The Error Response

JSON

```auto
{
    "errorCode": "400",
    "errorCategory": "Invalid-CSR",
    "errorMessage": "The provided Certificate Signing Request (CSR) is invalid."
}

```

### 5. My Specific Questions

1. Does the Simulation environment now require the **SAN (Subject Alternative Name)** to be encoded as a `GeneralName` of type `otherName` instead of `directoryName`?

2. Is there a specific requirement for the `Invoice Type` (0100 vs 1100) within the CSR for SaaS providers who don’t have a direct TIN/Portal access yet?

3. Are there any hidden characters or specific OIDs that the new Simulation engine (post-Sept 2025 update) expects which might differ from the standard SDK output?

I would highly appreciate any guidance or if you could take a quick look at a sample CSR generated by our system.

“MIICUDCCAfYCAQAwgcExHDAaBgNVBAMME1RTVC0zMTAxMjIzOTM1MDAwMDMxFDASBgNVBAoMC1hZWiBjb21wYW55MRQwEgYDVQQLDAtNYWluIEJyYW5jaDELMAkGA1UEBhMCU0ExOzA5BgNVBAUMMjEtVFNUfDItVFNUfDMtOThmOGMwZGMtYThiZi00MmRhLWFhNjUtZDczMWM2MTZlNzU5MRgwFgYDVQQaEw8zMTAxMjIzOTM1MDAwMDMxETAPBgNVBA8MCFNlcnZpY2VzMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEsXMs1zdOSrXGUoAT5fL5ZObskWhH2DKle7XYGdGwuIfeR2SvE3bnjpWdG4c6Di8ycYybBHqgmu/Xce9xJV5RSKCB1DCB0QYJKoZIhvcNAQkOMYHDMIHAMCQGCSsGAQQBgjcUAgQXExVQUkVaQVRDQS1Db2RlLVNpZ25pbmcwgZcGA1UdEQSBjzCBjAyBiVNOPTEtVFNUfDItVFNUfDMtOThmOGMwZGMtYThiZi00MmRhLWFhNjUtZDczMWM2MTZlNzU5LFVJRD0zMTAxMjIzOTM1MDAwMDMsdGl0bGU9MTEwMCxyZWdpc3RlcmVkQWRkcmVzcz1SUlJEMjkyOSxidXNpbmVzc0NhdGVnb3J5PVNlcnZpY2VzMAoGCCqGSM49BAMCA0gAMEUCIQDPG7ez21JzvZETXMfaJy2+mGopBpC3BdBIeQsV/qzfgQIgR2ZGWW4m3TgUc7LWdsjYX/GWq379rajxh1hX/+UaDhQ=”

**Best Regards,**

---

<div class="post-metadata">

**Author:** ![sergei.shishov](https://avatars.discourse-cdn.com/v4/letter/s/f0a364/32.png) [@sergei.shishov](https://zatca1.discourse.group/u/sergei.shishov)\
**Post date:** [June 10, 2026, 8:39am UTC](https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740/2 "2026-06-10T08:39:22Z")

</div>

You should not use TST as Zatca does not support it.

What you should use - is Simulation and it is completely different. There you have to enter “real” TRN and real OTP generated from the portal (simulation mode).

All other ways to test - are error-prone as not currently properly supported by ZATCA, the certificate the is hardcoded etc..

– Sergei

---

<div class="post-metadata">

**Author:** ![ialrasshid](https://avatars.discourse-cdn.com/v4/letter/i/ea5d25/32.png) [@ialrasshid](https://zatca1.discourse.group/u/ialrasshid)\
**Post date:** [August 16, 2026, 11:53am UTC](https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740/4 "2026-08-16T11:53:27Z")

</div>

How to use simulation mode

---

<div class="post-metadata">

**Author:** ![sergei.shishov](https://avatars.discourse-cdn.com/v4/letter/s/f0a364/32.png) [@sergei.shishov](https://zatca1.discourse.group/u/sergei.shishov)\
**Post date:** [September 5, 2026, 11:40am UTC](https://zatca1.discourse.group/t/technical-assistance-persistent-invalid-csr-error-in-zatca-simulation-environment-project-andalussystem/9740/5 "2026-09-05T11:40:35Z")

</div>

Hi, it is clearly stated in the documentation.

When you are generating a CSR, you have to specify the `1.3.6.1.4.1.311.20.2` policy according to your environment:

- development: `TSTZATCA-Code-Signing`
- simulation: `PREZATCA-Code-Signing`
- production: `ZATCA-Code-Signing`

NOTE: `development` should not be used at all (deprecated). You should use `simulation` for all your QA, staging, development, and testing.

– Sergei
