Sample code for 30+ languages & platforms
Dart

Paraguay E-Invoicing Signed XML (SIFEN)

See more XML Digital Signatures Examples

Demonstrates how to sign XML for e-invoicing -- SISTEMA INTEGRADO DE FACTURACIÓN ELECTRÓNICA NACIONAL (SIFEN). This is for signing XML files that need to be submitted to a government agency (Country Paraguay, SIFEN / EKUATIA, Sistema Nacional de Facturacion Electrónica).

Chilkat Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // Create the XML to be signed...

  // Use this online tool to generate code from sample XML: 
  // Generate Code to Create XML

  final xmlToSign = CkXml();
  xmlToSign.tag = 'rDE';
  xmlToSign.addAttribute('xmlns', 'http://ekuatia.set.gov.py/sifen/xsd');
  xmlToSign.addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
  xmlToSign.addAttribute('xsi:schemaLocation', 'http://ekuatia.set.gov.py/sifen/xsd siRecepDE_v150.xsd');
  xmlToSign.updateChildContent('dVerFor', '150');
  xmlToSign.updateAttrAt('DE', true, 'Id', '01800228774059001001501012022091519999999990');
  xmlToSign.updateChildContent('DE|dDVId', '0');
  xmlToSign.updateChildContent('DE|dFecFirma', '2022-09-15T10:23:05');
  xmlToSign.updateChildContent('DE|dSisFact', '1');
  xmlToSign.updateChildContent('DE|gOpeDE|iTipEmi', '1');
  xmlToSign.updateChildContent('DE|gOpeDE|dDesTipEmi', 'Normal');
  xmlToSign.updateChildContent('DE|gOpeDE|dCodSeg', '999999999');
  xmlToSign.updateChildContent('DE|gOpeDE|dInfoEmi', 'GENERADA DE PEDIDO 131043202');
  xmlToSign.updateChildContent('DE|gTimb|iTiDE', '1');
  xmlToSign.updateChildContent('DE|gTimb|dDesTiDE', 'Factura electr�nica');
  xmlToSign.updateChildContent('DE|gTimb|dNumTim', '18889014');
  xmlToSign.updateChildContent('DE|gTimb|dEst', '059');
  xmlToSign.updateChildContent('DE|gTimb|dPunExp', '001');
  xmlToSign.updateChildContent('DE|gTimb|dNumDoc', '0015010');
  xmlToSign.updateChildContent('DE|gTimb|dFeIniT', '2022-05-25');
  xmlToSign.updateChildContent('DE|gDatGralOpe|dFeEmiDE', '2022-09-15T10:22:57');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|iTipTra', '1');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesTipTra', 'Venta de mercader�a');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|iTImp', '1');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesTImp', 'IVA');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|cMoneOpe', 'PYG');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gOpeCom|dDesMoneOpe', 'Guarani');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dRucEm', '80022877');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDVEmi', '4');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|iTipCont', '1');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cTipReg', '1');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNomEmi', 'ABCDEF SA');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNomFanEmi', 'ABCDEF SA');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDirEmi', 'Jos� Abcde Xyz N� 666 e/Abxyz123');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dNumCas', '0');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dCompDir1', 'N/A');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dCompDir2', 'N/A');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cDepEmi', '12');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesDepEmi', 'CENTRAL');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cDisEmi', '153');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesDisEmi', 'CAPIATA');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|cCiuEmi', '1234');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDesCiuEmi', 'CAPIATA');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dTelEmi', '(022) 1111 000');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dEmailE', 'somebody@example.com.py');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|dDenSuc', 'PUNTO 99');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|gActEco|cActEco', '47721');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gEmis|gActEco|dDesActEco', 'COMERCIO AL POR MENOR DE PRODUCTOS');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iNatRec', '1');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iTiOpe', '2');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|cPaisRec', 'PRY');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dDesPaisRe', 'Paraguay');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|iTiContRec', '2');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dRucRec', '80082971');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dDVRec', '9');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNomRec', 'XXXXXXX');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNomFanRec', 'XXXXXXX');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dNumCasRec', '0');
  xmlToSign.updateChildContent('DE|gDatGralOpe|gDatRec|dCodCliente', '9999999');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamFE|iIndPres', '1');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamFE|dDesIndPres', 'Operaci�n presencial');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|iCondOpe', '1');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|dDCondOpe', 'Contado');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|iTiPago', '1');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dDesTiPag', 'Efectivo');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dMonTiPag', '100000.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|cMoneTiPag', 'PYG');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni|dDMoneTiPag', 'Guarani');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|iTiPago', '1');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dDesTiPag', 'Efectivo');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dMonTiPag', '73600.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|cMoneTiPag', 'PYG');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamCond|gPaConEIni[1]|dDMoneTiPag', 'Guarani');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dCodInt', '818181');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dDesProSer', 'Widget Abc Xyz');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|cUniMed', '77');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dDesUniMed', 'UNI');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|dCantProSer', '2.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|dPUniProSer', '16500.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|dTotBruOpeItem', '33000.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dDescItem', '3300.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dPorcDesIt', '20.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gValorItem|gValorRestaItem|dTotOpeItem', '26400.0000');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|iAfecIVA', '1');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dDesAfecIVA', 'Gravado IVA');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dPropIVA', '100');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dTasaIVA', '5');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dBasGravIVA', '25142.8571');
  xmlToSign.updateChildContent('DE|gDtipDE|gCamItem|gCamIVA|dLiqIVAItem', '1257.1429');
  xmlToSign.updateChildContent('DE|gTotSub|dSubExe', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dSub5', '26400.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dSub10', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotOpe', '26400.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotDesc', '6600.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotDescGlotem', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotAntItem', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotAnt', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dPorcDescTotal', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dDescTotal', '6600.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dAnticipo', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dRedon', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotGralOpe', '26400.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dIVA5', '1257.1429');
  xmlToSign.updateChildContent('DE|gTotSub|dIVA10', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTotIVA', '1257.1429');
  xmlToSign.updateChildContent('DE|gTotSub|dBaseGrav5', '25142.8571');
  xmlToSign.updateChildContent('DE|gTotSub|dBaseGrav10', '0.0000');
  xmlToSign.updateChildContent('DE|gTotSub|dTBasGraIVA', '25142.8571');

  final gen = CkXmlDSigGen();

  gen.sigLocation = 'rDE';
  gen.sigLocationMod = 0;
  gen.sigNamespacePrefix = '';
  gen.sigNamespaceUri = 'http://www.w3.org/2000/09/xmldsig#';
  gen.signedInfoCanonAlg = 'C14N';
  gen.signedInfoDigestMethod = 'sha256';

  // -------- Reference 1 --------
  final xml1 = CkXml();
  xml1.tag = 'Transforms';
  xml1.updateAttrAt('Transform', true, 'Algorithm', 'http://www.w3.org/2000/09/xmldsig#enveloped-signature');
  xml1.updateAttrAt('Transform[1]', true, 'Algorithm', 'http://www.w3.org/2001/10/xml-exc-c14n#');

  gen.addSameDocRef2('01800228774059001001501012022091516941989060', 'sha256', xml1, '');

  // Provide a certificate + private key. (PFX password is test123)
  final cert = CkCert();
  try {
    cert.loadPfxFile('qa_data/pfx/cert_test123.pfx', 'test123');
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  gen.setX509Cert(cert, true);

  gen.keyInfoType = 'X509Data';
  gen.x509Type = 'Certificate';

  // Load XML to be signed...
  final sbXml = CkStringBuilder();
  xmlToSign.getXmlSb(sbXml);

  gen.behaviors = 'IndentedSignature';

  // Sign the XML...
  try {
    gen.createXmlDSigSb(sbXml);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // -----------------------------------------------

  // Save the signed XML to a file.
  sbXml.writeFile('c:/temp/qa_output/signedXml.xml', 'utf-8', false);

  print(sbXml.getAsString());

  // ----------------------------------------
  // Verify the signatures we just produced...
  final verifier = CkXmlDSig();
  try {
    verifier.loadSignatureSb(sbXml);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final numSigs = verifier.numSignatures;
  var verifyIdx = 0;
  while (verifyIdx < numSigs) {
    verifier.selector = verifyIdx;
    try {
      verifier.verifySignature(true);
    } on ChilkatException catch (e) {
      print(e.lastErrorText);
      return;
    }

    verifyIdx++;
  }

  print('All signatures were successfully verified.');
}