Swift
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
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.")
}