Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

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 Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.StringBuilder,
  Chilkat.XmlDSigGen,
  Chilkat.Xml,
  Chilkat.XmlDSig,
  Chilkat.Cert;

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

procedure RunDemo;
var
  success: Boolean;
  xmlToSign: TXml;
  gen: TXmlDSigGen;
  xml1: TXml;
  cert: TCert;
  sbXml: TStringBuilder;
  verifier: TXmlDSig;
  numSigs: Integer;
  verifyIdx: Integer;
  verified: Boolean;

begin
  success := False;

  success := True;

  //  Create the XML to be signed...

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

  xmlToSign := TXml.Create;
  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');

  gen := TXmlDSigGen.Create;

  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 --------
  xml1 := TXml.Create;
  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)
  cert := TCert.Create;
  success := cert.LoadPfxFile('qa_data/pfx/cert_test123.pfx','test123');
  if (success <> True) then
    begin
      WriteLn(cert.LastErrorText);
      Exit;
    end;
  gen.SetX509Cert(cert,True);

  gen.KeyInfoType := 'X509Data';
  gen.X509Type := 'Certificate';

  //  Load XML to be signed...
  sbXml := TStringBuilder.Create;
  xmlToSign.GetXmlSb(sbXml);

  gen.Behaviors := 'IndentedSignature';

  //  Sign the XML...
  success := gen.CreateXmlDSigSb(sbXml);
  if (success <> True) then
    begin
      WriteLn(gen.LastErrorText);
      Exit;
    end;
  //  -----------------------------------------------

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

  WriteLn(sbXml.GetAsString());

  //  ----------------------------------------
  //  Verify the signatures we just produced...
  verifier := TXmlDSig.Create;
  success := verifier.LoadSignatureSb(sbXml);
  if (success <> True) then
    begin
      WriteLn(verifier.LastErrorText);
      Exit;
    end;

  numSigs := verifier.NumSignatures;
  verifyIdx := 0;
  while verifyIdx < numSigs do
    begin
      verifier.Selector := verifyIdx;
      verified := verifier.VerifySignature(True);
      if (verified <> True) then
        begin
          WriteLn(verifier.LastErrorText);
          Exit;
        end;
      verifyIdx := verifyIdx + 1;
    end;

  WriteLn('All signatures were successfully verified.');


  xmlToSign.Free;
  gen.Free;
  xml1.Free;
  cert.Free;
  sbXml.Free;
  verifier.Free;

end;

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

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.