einvoicesign

Signs UBL 2.1 documents with an enveloped XML-DSig signature — pure Dart, no OpenSSL or other native dependencies. Runs on Windows and Linux servers.

Built and validated for Croatian eInvoices (eRačun, Fiscalization 2.0), but it works with any UBL 2.1 document (Invoice, CreditNote, …) that contains the standard OASIS UBL signature extension placeholder (see below). Note the signature profile: plain XML-DSig without XAdES qualifying properties — this is what the Croatian scheme expects; national schemes that require XAdES or PEPPOL BIS (which does not use enveloped document signatures) need a different tool.

The output is byte-compatible with .NET SignedXml at the canonical level: the test suite reproduces a reference signature produced by the original C# tool character-for-character.

Features

  • Exclusive XML Canonicalization 1.0 (xml-exc-c14n#), own implementation
  • RSA-SHA256 (PKCS#1 v1.5) signature, SHA-256 digest
  • Reference URI="" with enveloped-signature + exc-c14n transforms
  • Certificate loaded from a PKCS#12 (.p12/.pfx) file via pkcs12_parser, embedded in KeyInfo/X509Data
  • The signature is appended to ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ sig:UBLDocumentSignatures/sac:SignatureInformation — the standard OASIS UBL 2.1 signature extension, which must already exist (empty) in the document

CLI

dart pub global activate einvoicesign
einvoicesign invoice.xml cert.p12 password

The signed document is written next to the input as invoice_signed.xml. Exit codes: 0 OK, 1 bad arguments, 2 error.

For a standalone server binary:

dart compile exe bin/einvoicesign.dart -o einvoicesign.exe   # Windows
dart compile exe bin/einvoicesign.dart -o einvoicesign       # Linux

Library

import 'dart:io';
import 'package:einvoicesign/einvoicesign.dart';

final signedXml = signInvoiceXml(
  File('invoice.xml').readAsStringSync(),
  File('cert.p12').readAsBytesSync(),
  'password',
);

canonicalizeDocument and canonicalizeSubtree (exclusive C14N) are also exported and can be used on their own, e.g. for signature verification.

Testing

dart test — compatibility with .NET is proven against a reference output of the original C# SignedXml tool (test/fixtures/F0001904_signed.xml): the document digest matches byte-for-byte, and because RSA PKCS#1 v1.5 is deterministic, the produced SignatureValue is identical to the .NET one. All test certificates are throwaway self-signed certificates generated for the test suite.

Libraries

einvoicesign
Croatian eInvoice (UBL 2.1) XML-DSig signer — Dart port of the C# EInvoiceSign tool.