Master ZATCA QR code TLV encoding, Base64 conversion, SHA-256 hashing, and ECDSA digital signatures for Saudi e-invoicing. Read our technical deep dive today.
In modern enterprise operations, implementing Technical Deep Dive: TLV Encoding and ECDSA Signatures in Saudi E-Invoicing has become a vital strategic imperative. As organizations expand their operations across regional and international markets, aligning operational processes with Type–length–value standards is essential for sustained growth.
How Tag-Length-Value (TLV) base64 structures are constructed and signed according to ZATCA standards.
Modern enterprises operating in competitive regional markets like Saudi Arabia cannot afford disconnected information silos. Real-time data synchronization between back-office accounting, warehouse inventory, and customer-facing touchpoints directly dictates commercial agility.
A structured implementation roadmap requires disciplined requirement gathering, solution blueprinting, and sandbox validation. Key considerations include:
Following deployment, organizations should benchmark operational improvements against defined Key Performance Indicators (KPIs). Routine metrics include order fulfillment lead times, financial closing duration, and end-user workflow efficiency. Impleway's certified consultants work closely with leadership teams to ensure long-term value realization.
Under the e-invoicing regulations promulgated by the Zakat, Tax and Customs Authority (ZATCA) in the Kingdom of Saudi Arabia, the technical requirements for invoice Quick Response (QR) codes evolved dramatically between Phase 1 (Generation Phase) and Phase 2 (Integration Phase). In Phase 1, many vendors rendered simple URL strings or plain text values inside QR codes. Under Phase 2 regulations, rendering plain text, web hyperlinks, or unformatted JSON strings is strictly non-compliant and will result in immediate rejection by statutory validation engines.
ZATCA Phase 2 mandates a binary Tag-Length-Value (TLV) byte-level data structure encoded into a standard Base64 string. For B2C Simplified Tax Invoices, the QR code serves as an autonomous, self-verifying cryptographic artifact. It must encode nine mandatory fields—including the invoice SHA-256 digest, the ECDSA digital signature, and the taxpayer's public key certificate—allowing tax inspectors and end consumers to verify invoice authenticity offline using the official ZATCA mobile scanning application without needing an active internet connection. Learn about our compliance development services on our Custom Software Development page or explore comprehensive ERP tax localization under our ERP Implementation Services.
TLV is a lightweight binary encoding scheme widely utilized in telecommunications and smart card security standards. Each data element is constructed as a continuous byte triplet composed of three sequential components: Tag (a 1-byte identifier specifying the field number), Length (a 1-byte value defining the exact byte length of the value), and Value (the raw byte sequence representing the UTF-8 text or binary payload).
| Tag Number | Field Name & Description | Data Type & Encoding | Phase 2 Requirement Status |
|---|---|---|---|
| Tag 1 | Seller's Commercial Entity Name | UTF-8 String (multi-byte Arabic/English) | Mandatory for all invoices |
| Tag 2 | VAT Registration Number (15 digits) | UTF-8 Numeric String (starts/ends with 3) | Mandatory for all invoices |
| Tag 3 | Invoice Generation Timestamp | ISO 8601 (YYYY-MM-DDTHH:MM:SSZ) | Mandatory for all invoices |
| Tag 4 | Invoice Total Amount (Inc. VAT) | UTF-8 String formatted to 2 decimals | Mandatory for all invoices |
| Tag 5 | Total VAT Tax Amount | UTF-8 String formatted to 2 decimals | Mandatory for all invoices |
| Tag 6 | Invoice SHA-256 Hash Digest | Raw Byte Buffer / Hex / Base64 | Mandatory for Phase 2 Simplified Invoices |
| Tag 7 | ECDSA Cryptographic Signature | Binary Signature (secp256k1 curve) | Mandatory for Phase 2 Simplified Invoices |
| Tag 8 | ECDSA Public Key Buffer | Raw Public Key Bytes | Mandatory for Phase 2 Simplified Invoices |
| Tag 9 | Cryptographic Stamp (X.509 Certificate) | Raw Certificate Bytes | Mandatory for Phase 2 Simplified Invoices |
A critical engineering pitfall when packing TLV buffers in modern programming languages (such as JavaScript, Python, or C#) is miscalculating byte lengths. In languages where strings are treated as UTF-16, checking string.length for Arabic text returns the character count, NOT the UTF-8 byte count. Because Arabic characters consume two bytes in UTF-8 encoding, using character length corrupts the TLV byte stream, leading to instant QR code decoding failure by the ZATCA validator.
The proper byte-packing algorithm requires converting each value into a raw UTF-8 byte buffer first, measuring the exact buffer.length, and sequentially concatenating the Tag byte, Length byte, and Value buffer:
// Production Node.js TLV Byte Packing Routine
function encodeTLV(tag, value) {
const valueBuffer = Buffer.from(value, 'utf8');
const tagBuffer = Buffer.from([tag]);
const lengthBuffer = Buffer.from([valueBuffer.length]);
return Buffer.concat([tagBuffer, lengthBuffer, valueBuffer]);
}
// Concatenate all 9 tags sequentially into final buffer
const qrBuffer = Buffer.concat([
encodeTLV(1, sellerName),
encodeTLV(2, vatNumber),
encodeTLV(3, timestamp),
encodeTLV(4, invoiceTotal),
encodeTLV(5, vatTotal),
encodeTLV(6, invoiceHash),
encodeTLV(7, ecdsaSignature),
encodeTLV(8, publicKey),
encodeTLV(9, certificateStamp)
]);
// Final output for QR code rendering:
const base64QR = qrBuffer.toString('base64');
Generating Tag 6 (Invoice Hash) and Tag 7 (Digital Signature) requires strict cryptographic pre-processing. Before an invoice can be hashed, the raw UBL 2.1 XML document must undergo Canonicalization according to the C14N11 standard. This process removes non-significant whitespace, strips comments, and normalizes XML namespaces. Furthermore, the XML elements corresponding to the digital signature placeholder, the cryptographic stamp, and the QR code itself are stripped from the canonical payload to prevent circular reference paradoxes.
The canonical XML string is hashed using the SHA-256 cryptographic algorithm, producing a 32-byte digest. For Simplified Invoices, this digest is digitally signed using the taxpayer's ECDSA private key (secp256k1 curve) issued during initial device onboarding via the ZATCA Fatoora Compliance CSID (CCSID) portal. Discover how our certified integration modules work with Odoo ERP Services and explore our full IT capabilities on our Services Suite.
Once the Base64 QR code string is generated, it must be embedded within the standardized UBL 2.1 XML file under the cac:AdditionalDocumentReference structure with cbc:ID set to 'QR' and the payload stored inside cbc:EmbeddedDocumentBinaryObject with mimeCode 'text/plain'. When generating the visual human-readable thermal receipt or PDF/A-3 document, this Base64 string is converted into a standard 2D QR barcode graphic printed on the customer receipt.
In high-volume retail and point-of-sale (POS) environments, encoding speed is critical. Generating cryptographic digests, assembling binary TLV buffers, and rendering QR graphics must execute in under 150 milliseconds to avoid checkout queue delays. Optimized implementations pre-compile standard Tag structures, cache seller master metadata in memory, and offload ECDSA signing operations to asynchronous worker threads or cryptographic hardware accelerators. This ensures seamless customer throughput during peak trading periods while guaranteeing 100% compliance with ZATCA Phase 2 technical standards.
Connect with our senior cryptography and e-invoicing architects via our Advisory Desk to audit your ZATCA Phase 2 compliance engine.
This error almost universally stems from using string character length instead of UTF-8 byte buffer length. Arabic characters require two bytes in UTF-8; calculating length using character count results in a truncated length header that corrupts ZATCA parser deserialization.
In UTF-8, English ASCII characters take 1 byte while Arabic characters take 2 bytes. If a 10-character Arabic name is evaluated with string.length (10), but occupies 20 bytes in memory, the TLV decoder reads only the first 10 bytes, corrupting subsequent tags.
B2B Standard Tax Invoices must be cleared synchronously in real time via ZATCA Fatoora APIs before issuance, and ZATCA provides the official QR code stamp. In contrast, B2C Simplified Tax Invoices are signed locally by the POS/ERP, printed immediately, and reported asynchronously within 24 hours.
ZATCA Phase 2 mandates the Elliptic Curve Digital Signature Algorithm (ECDSA) using the secp256k1 curve with SHA-256 digests. Cryptographic keys and CSRs generated for CCSID/PCSID onboarding must strictly follow this cryptographic specification.