Sample code for 30+ languages & platforms
Objective-C

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 Objective-C Downloads

Objective-C
#import <CkoXml.h>
#import <CkoXmlDSigGen.h>
#import <CkoCert.h>
#import <CkoStringBuilder.h>
#import <CkoXmlDSig.h>

BOOL success = NO;

success = YES;

// Create the XML to be signed...

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

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

CkoXmlDSigGen *gen = [[CkoXmlDSigGen alloc] init];

gen.SigLocation = @"rDE";
gen.SigLocationMod = [NSNumber numberWithInt:0];
gen.SigNamespacePrefix = @"";
gen.SigNamespaceUri = @"http://www.w3.org/2000/09/xmldsig#";
gen.SignedInfoCanonAlg = @"C14N";
gen.SignedInfoDigestMethod = @"sha256";

// -------- Reference 1 --------
CkoXml *xml1 = [[CkoXml alloc] init];
xml1.Tag = @"Transforms";
[xml1 UpdateAttrAt: @"Transform" autoCreate: YES attrName: @"Algorithm" attrValue: @"http://www.w3.org/2000/09/xmldsig#enveloped-signature"];
[xml1 UpdateAttrAt: @"Transform[1]" autoCreate: YES attrName: @"Algorithm" attrValue: @"http://www.w3.org/2001/10/xml-exc-c14n#"];

[gen AddSameDocRef2: @"01800228774059001001501012022091516941989060" digestMethod: @"sha256" transforms: xml1 refType: @""];

// Provide a certificate + private key. (PFX password is test123)
CkoCert *cert = [[CkoCert alloc] init];
success = [cert LoadPfxFile: @"qa_data/pfx/cert_test123.pfx" password: @"test123"];
if (success != YES) {
    NSLog(@"%@",cert.LastErrorText);
    return;
}

[gen SetX509Cert: cert usePrivateKey: YES];

gen.KeyInfoType = @"X509Data";
gen.X509Type = @"Certificate";

// Load XML to be signed...
CkoStringBuilder *sbXml = [[CkoStringBuilder alloc] init];
[xmlToSign GetXmlSb: sbXml];

gen.Behaviors = @"IndentedSignature";

// Sign the XML...
success = [gen CreateXmlDSigSb: sbXml];
if (success != YES) {
    NSLog(@"%@",gen.LastErrorText);
    return;
}

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

// Save the signed XML to a file.
success = [sbXml WriteFile: @"c:/temp/qa_output/signedXml.xml" charset: @"utf-8" emitBom: NO];

NSLog(@"%@",[sbXml GetAsString]);

// ----------------------------------------
// Verify the signatures we just produced...
CkoXmlDSig *verifier = [[CkoXmlDSig alloc] init];
success = [verifier LoadSignatureSb: sbXml];
if (success != YES) {
    NSLog(@"%@",verifier.LastErrorText);
    return;
}

int numSigs = [verifier.NumSignatures intValue];
int verifyIdx = 0;
while (verifyIdx < numSigs) {
    verifier.Selector = [NSNumber numberWithInt: verifyIdx];
    BOOL verified = [verifier VerifySignature: YES];
    if (verified != YES) {
        NSLog(@"%@",verifier.LastErrorText);
        return;
    }

    verifyIdx = verifyIdx + 1;
}

NSLog(@"%@",@"All signatures were successfully verified.");