Sample code for 30+ languages & platforms
Swift

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 Swift Downloads

Swift

func chilkatTest() {
    var success: Bool = false

    success = true

    // Create the XML to be signed...

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

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

    let gen = CkoXmlDSigGen()!

    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 --------
    let xml1 = CkoXml()!
    xml1.tag = "Transforms"
    xml1.updateAttrAt(tagPath: "Transform", autoCreate: true, attrName: "Algorithm", attrValue: "http://www.w3.org/2000/09/xmldsig#enveloped-signature")
    xml1.updateAttrAt(tagPath: "Transform[1]", autoCreate: true, attrName: "Algorithm", attrValue: "http://www.w3.org/2001/10/xml-exc-c14n#")

    gen.addSameDocRef2(id: "01800228774059001001501012022091516941989060", digestMethod: "sha256", transforms: xml1, refType: "")

    // Provide a certificate + private key. (PFX password is test123)
    let cert = CkoCert()!
    success = cert.loadPfxFile(path: "qa_data/pfx/cert_test123.pfx", password: "test123")
    if success != true {
        print("\(cert.lastErrorText!)")
        return
    }

    gen.setX509Cert(cert: cert, usePrivateKey: true)

    gen.keyInfoType = "X509Data"
    gen.x509Type = "Certificate"

    // Load XML to be signed...
    let sbXml = CkoStringBuilder()!
    xmlToSign.getSb(sb: sbXml)

    gen.behaviors = "IndentedSignature"

    // Sign the XML...
    success = gen.createXmlDSigSb(sbXml: sbXml)
    if success != true {
        print("\(gen.lastErrorText!)")
        return
    }

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

    // Save the signed XML to a file.
    success = sbXml.writeFile(path: "c:/temp/qa_output/signedXml.xml", charset: "utf-8", emitBom: false)

    print("\(sbXml.getAsString()!)")

    // ----------------------------------------
    // Verify the signatures we just produced...
    let verifier = CkoXmlDSig()!
    success = verifier.loadSignatureSb(sbXmlSig: sbXml)
    if success != true {
        print("\(verifier.lastErrorText!)")
        return
    }

    var numSigs: Int = verifier.numSignatures.intValue
    var verifyIdx: Int = 0
    while verifyIdx < numSigs {
        verifier.selector = verifyIdx
        var verified: Bool = verifier.verifySignature(verifyReferenceDigests: true)
        if verified != true {
            print("\(verifier.lastErrorText!)")
            return
        }

        verifyIdx = verifyIdx + 1
    }

    print("All signatures were successfully verified.")

}