Skip to content

Invoice Signing

C signatures use the C API. See C and C++ bindings for ownership and build instructions. The declarations below come from the generated headers. C++ exposes the same types in namespace fatoora through fatoora/Type.hpp headers.

Signing helpers and signature metadata.

InvoiceSigner / Signer

from_pem

Create signer from PEM

Create a signer from PEM-encoded certificate and private key.

InvoiceSigner::from_pem(cert_pem: &str, key_pem: &str) -> Result<InvoiceSigner, SigningError>
Signer.from_pem(cert_pem: str, key_pem: str) -> Signer
#include "fatoora.h"

FatooraStatus fatoora_signer_from_pem(const char *cert_pem,
    const char *key_pem,
    FatooraSigner **out,
    FatooraError **error);

from_der

Create signer from DER

Create a signer from DER-encoded certificate and private key.

InvoiceSigner::from_der(cert_der: &[u8], key_der: &[u8]) -> Result<InvoiceSigner, SigningError>
Signer.from_der(cert_der: bytes, key_der: bytes) -> Signer
#include "fatoora.h"

FatooraStatus fatoora_signer_from_der(const uint8_t *cert_der,
    size_t cert_der_len,
    const uint8_t *key_der,
    size_t key_der_len,
    FatooraSigner **out,
    FatooraError **error);

certificate_pem

Read signer certificate as PEM
InvoiceSigner::certificate_pem(&self) -> Result<String, SigningError>
Signer.certificate_pem() -> str
#include "fatoora.h"

FatooraStatus fatoora_signer_certificate_pem(const FatooraSigner *self,
    char **out,
    FatooraError **error);

certificate_der

Read signer certificate as DER
InvoiceSigner::certificate_der(&self) -> Result<Vec<u8>, SigningError>
Signer.certificate_der() -> bytes
#include "fatoora.h"

FatooraStatus fatoora_signer_certificate_der(const FatooraSigner *self,
    FatooraBytes **out,
    FatooraError **error);

sign_xml

InvoiceSigner::sign_xml(&self, xml: &str) -> Result<String, SigningError>

Signs pre-built XML and returns the signed XML string. This does not construct a SignedInvoice or run its invoice-model parsing checks. The input is parsed and serialized, so its original byte representation is not preserved. Keep the returned signed XML unchanged. Signing does not establish invoice compliance.

See signed XML ownership for borrowed, copied, and consuming access to SignedInvoice XML.

FinalizedInvoice

sign

Sign finalized invoice

Sign finalized invoice XML and return a signed invoice.

FinalizedInvoice::sign(self, signer: &InvoiceSigner) -> Result<SignedInvoice, SigningError>
FinalizedInvoice.sign(signer: Signer) -> SignedInvoice
#include "fatoora.h"

FatooraStatus fatoora_signer_sign(const FatooraSigner *self,
    FatooraFinalizedInvoice *invoice,
    FatooraSignedInvoice **out,
    FatooraError **error);

SignedInvoice

xml

Get signed XML
SignedInvoice::xml(&self) -> &str
SignedInvoice.xml() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_xml(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

to_xml_base64

Get signed XML as Base64
SignedInvoice::to_xml_base64(&self) -> String
SignedInvoice.to_xml_base64() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_to_xml_base64(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

qr_code

Get QR payload
SignedInvoice::qr_code(&self) -> &str
SignedInvoice.qr_code() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_qr_code(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

invoice_hash

Get invoice hash
SignedInvoice::invoice_hash(&self) -> &str
SignedInvoice.invoice_hash() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_invoice_hash(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

hash_base64

Get invoice hash as Base64
SignedInvoice::hash_base64(&self) -> Result<String, SigningError>
SignedInvoice.hash_base64() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_hash_base64(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

signature

Get signature value
SignedInvoice::signature(&self) -> &str
SignedInvoice.signature() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_signature(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

public_key

Get public key
SignedInvoice::public_key(&self) -> &str
SignedInvoice.public_key() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_public_key(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

zatca_key_signature

Get optional ZATCA key signature
SignedInvoice::zatca_key_signature(&self) -> Option<&str>
SignedInvoice.zatca_key_signature() -> Optional[str]
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_zatca_key_signature(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

signed_props_hash

Get signed properties hash
SignedProperties::signed_props_hash(&self) -> &str
SignedInvoice.signed_props_hash() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_signed_props_hash(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

cert_hash

Get certificate hash
SignedInvoice.cert_hash() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_cert_hash(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

signing_time

Get signing timestamp
SignedInvoice.signing_time() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_signing_time(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

issuer

Get certificate issuer from signed properties
SignedProperties::issuer(&self) -> &str
SignedInvoice.issuer() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_issuer(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

serial

Get certificate serial from signed properties
SignedProperties::serial(&self) -> &str
SignedInvoice.serial() -> str
#include "fatoora.h"

FatooraStatus fatoora_signed_invoice_serial(const FatooraSignedInvoice *self,
    char **out,
    FatooraError **error);

invoice_hash_base64_from_xml_str

hash from XML

Compute invoice hash (Base64)

Compute invoice hash from XML and return it as Base64.

invoice_hash_base64_from_xml_str(xml: &str) -> Result<String, SigningError>

Errors

Errors

  • SigningError covers XML parsing, canonicalization, and certificate/key errors.

Notes

Notes

  • SignedProperties::signing_time uses YYYY-MM-DDTHH:MM:SS format (UTC).
  • Invoice hashes are computed from canonicalized XML excluding signature fields.

See also: Invoice Signing Guide