PureBasic
PureBasic
Create JPK_VAT XaDES-BES Signed XML
See more XAdES Examples
Demonstrates how to sign XML for JPK_VAT.Chilkat PureBasic Downloads
IncludeFile "CkCert.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkXmlDSigGen.pb"
IncludeFile "CkXmlDSig.pb"
IncludeFile "CkStringBuilder.pb"
Procedure ChilkatExample()
success.i = 0
; This example requires the Chilkat API to have been previously unlocked.
; See Global Unlock Sample for sample code.
; This example will sign the following XML document:
; <?xml version="1.0" encoding="utf-8"?>
; <InitUpload xmlns="http://e-dokumenty.mf.gov.pl">
; <DocumentType>JPK</DocumentType>
; <Version>01.02.01.20160617</Version>
; <EncryptionKey algorithm="RSA" encoding="Base64" mode="ECB" padding="PKCS#1">...</EncryptionKey>
; <DocumentList>
; <Document>
; <FormCode schemaVersion="1-1" systemCode="JPK_VAT (3)">JPK_VAT</FormCode>
; <FileName>JPK_VAT_3_v1-1_20181208.xml</FileName>
; <ContentLength>8736</ContentLength>
; <HashValue algorithm="SHA-256" encoding="Base64">JEEI1pItwh6dj/Xe1uts/x61qnjZ4DLHpkRMhmf1oQQ=</HashValue>
; <FileSignatureList filesNumber="1">
; <Packaging>
; <SplitZip mode="zip" type="split"/>
; </Packaging>
; <Encryption>
; <AES block="16" mode="CBC" padding="PKCS#7" size="256">
; <IV bytes="16" encoding="Base64">FFsCRAPYJD3J6cRvd44UDA==</IV>
; </AES>
; </Encryption>
; <FileSignature>
; <OrdinalNumber>1</OrdinalNumber>
; <FileName>JPK_VAT_3_v1-1_20181208-000.xml.zip.aes</FileName>
; <ContentLength>16</ContentLength>
; <HashValue algorithm="MD5" encoding="Base64">BX2DTD3ASC/zF6aq/012Cg==</HashValue>
; </FileSignature>
; </FileSignatureList>
; </Document>
; </DocumentList>
; </InitUpload>
; First we build the XML to be signed.
;
; Use this online tool to generate the code from sample XML:
; Generate Code to Create XML
success = 1
xmlToSign.i = CkXml::ckCreate()
If xmlToSign.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::setCkTag(xmlToSign, "InitUpload")
CkXml::ckAddAttribute(xmlToSign,"xmlns","http://e-dokumenty.mf.gov.pl")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentType","JPK")
CkXml::ckUpdateChildContent(xmlToSign,"Version","01.02.01.20160617")
CkXml::ckUpdateAttrAt(xmlToSign,"EncryptionKey",1,"algorithm","RSA")
CkXml::ckUpdateAttrAt(xmlToSign,"EncryptionKey",1,"encoding","Base64")
CkXml::ckUpdateAttrAt(xmlToSign,"EncryptionKey",1,"mode","ECB")
CkXml::ckUpdateAttrAt(xmlToSign,"EncryptionKey",1,"padding","PKCS#1")
CkXml::ckUpdateChildContent(xmlToSign,"EncryptionKey","...")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FormCode",1,"schemaVersion","1-1")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FormCode",1,"systemCode","JPK_VAT (3)")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FormCode","JPK_VAT")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileName","JPK_VAT_3_v1-1_20181208.xml")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|ContentLength","8736")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|HashValue",1,"algorithm","SHA-256")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|HashValue",1,"encoding","Base64")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|HashValue","JEEI1pItwh6dj/Xe1uts/x61qnjZ4DLHpkRMhmf1oQQ=")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList",1,"filesNumber","1")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Packaging|SplitZip",1,"mode","zip")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Packaging|SplitZip",1,"type","split")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES",1,"block","16")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES",1,"mode","CBC")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES",1,"padding","PKCS#7")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES",1,"size","256")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES|IV",1,"bytes","16")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES|IV",1,"encoding","Base64")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileSignatureList|Encryption|AES|IV","FFsCRAPYJD3J6cRvd44UDA==")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|OrdinalNumber","1")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|FileName","JPK_VAT_3_v1-1_20181208-000.xml.zip.aes")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|ContentLength","16")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|HashValue",1,"algorithm","MD5")
CkXml::ckUpdateAttrAt(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|HashValue",1,"encoding","Base64")
CkXml::ckUpdateChildContent(xmlToSign,"DocumentList|Document|FileSignatureList|FileSignature|HashValue","BX2DTD3ASC/zF6aq/012Cg==")
; Also see the online tool to generate the code from sample already-signed XML:
; Generate XML Signature Creation Code from an Already-Signed XML Sample
gen.i = CkXmlDSigGen::ckCreate()
If gen.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXmlDSigGen::setCkSigLocation(gen, "InitUpload")
CkXmlDSigGen::setCkSigId(gen, "id-1234")
CkXmlDSigGen::setCkSigNamespacePrefix(gen, "ds")
CkXmlDSigGen::setCkSigNamespaceUri(gen, "http://www.w3.org/2000/09/xmldsig#")
CkXmlDSigGen::setCkSignedInfoCanonAlg(gen, "EXCL_C14N")
CkXmlDSigGen::setCkSignedInfoDigestMethod(gen, "sha256")
; Create an Object to be added to the Signature.
object1.i = CkXml::ckCreate()
If object1.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::setCkTag(object1, "xades:QualifyingProperties")
CkXml::ckAddAttribute(object1,"Target","#id-1234")
CkXml::ckAddAttribute(object1,"xmlns:xades","http://uri.etsi.org/01903/v1.3.2#")
CkXml::ckUpdateAttrAt(object1,"xades:SignedProperties",1,"Id","xades-id-1234")
CkXml::ckUpdateChildContent(object1,"xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime","TO BE GENERATED BY CHILKAT")
CkXml::ckUpdateAttrAt(object1,"xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestMethod",1,"Algorithm","http://www.w3.org/2001/04/xmlenc#sha256")
CkXml::ckUpdateChildContent(object1,"xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestValue","TO BE GENERATED BY CHILKAT")
CkXml::ckUpdateChildContent(object1,"xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:IssuerSerialV2","TO BE GENERATED BY CHILKAT")
CkXml::ckUpdateAttrAt(object1,"xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat",1,"ObjectReference","#r-id-1")
CkXml::ckUpdateChildContent(object1,"xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:MimeType","text/xml")
CkXmlDSigGen::ckAddObject(gen,"",CkXml::ckGetXml(object1),"","")
; -------- Reference 1 --------
xml1.i = CkXml::ckCreate()
If xml1.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::setCkTag(xml1, "ds:Transforms")
CkXml::ckUpdateAttrAt(xml1,"ds:Transform",1,"Algorithm","http://www.w3.org/TR/1999/REC-xpath-19991116")
CkXml::ckUpdateChildContent(xml1,"ds:Transform|ds:XPath","not(ancestor-or-self::ds:Signature)")
CkXml::ckUpdateAttrAt(xml1,"ds:Transform[1]",1,"Algorithm","http://www.w3.org/2001/10/xml-exc-c14n#")
CkXmlDSigGen::ckAddSameDocRef2(gen,"","sha256",xml1,"")
CkXmlDSigGen::ckSetRefIdAttr(gen,"","r-id-1")
; -------- Reference 2 --------
xml2.i = CkXml::ckCreate()
If xml2.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::setCkTag(xml2, "ds:Transforms")
CkXml::ckUpdateAttrAt(xml2,"ds:Transform",1,"Algorithm","http://www.w3.org/2001/10/xml-exc-c14n#")
CkXmlDSigGen::ckAddObjectRef2(gen,"xades-id-1234","sha256",xml2,"http://uri.etsi.org/01903#SignedProperties")
; Provide a certificate + private key. (PFX password is test123)
; See Load Certificate on Smartcard for an example showing how to load the cert from a smartcard..
cert.i = CkCert::ckCreate()
If cert.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkCert::ckLoadPfxFile(cert,"qa_data/pfx/cert_test123.pfx","test123")
If success <> 1
Debug CkCert::ckLastErrorText(cert)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkXml::ckDispose(object1)
CkXml::ckDispose(xml1)
CkXml::ckDispose(xml2)
CkCert::ckDispose(cert)
ProcedureReturn
EndIf
CkXmlDSigGen::ckSetX509Cert(gen,cert,1)
CkXmlDSigGen::setCkKeyInfoType(gen, "X509Data")
CkXmlDSigGen::setCkX509Type(gen, "Certificate")
; Load XML to be signed...
sbXml.i = CkStringBuilder::ckCreate()
If sbXml.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::ckGetXmlSb(xmlToSign,sbXml)
CkXmlDSigGen::setCkBehaviors(gen, "IndentedSignature,TransformSignatureXPath,IssuerSerialHex")
; Sign the XML...
success = CkXmlDSigGen::ckCreateXmlDSigSb(gen,sbXml)
If success <> 1
Debug CkXmlDSigGen::ckLastErrorText(gen)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkXml::ckDispose(object1)
CkXml::ckDispose(xml1)
CkXml::ckDispose(xml2)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
ProcedureReturn
EndIf
; Save the signed XMl to a file.
success = CkStringBuilder::ckWriteFile(sbXml,"qa_output/signedXml.xml","utf-8",0)
Debug CkStringBuilder::ckGetAsString(sbXml)
; ----------------------------------------
; Verify the signature we just produced...
verifier.i = CkXmlDSig::ckCreate()
If verifier.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkXmlDSig::ckLoadSignatureSb(verifier,sbXml)
If success <> 1
Debug CkXmlDSig::ckLastErrorText(verifier)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkXml::ckDispose(object1)
CkXml::ckDispose(xml1)
CkXml::ckDispose(xml2)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndIf
verified.i = CkXmlDSig::ckVerifySignature(verifier,1)
If verified <> 1
Debug CkXmlDSig::ckLastErrorText(verifier)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkXml::ckDispose(object1)
CkXml::ckDispose(xml1)
CkXml::ckDispose(xml2)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndIf
Debug "This signature was successfully verified."
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkXml::ckDispose(object1)
CkXml::ckDispose(xml1)
CkXml::ckDispose(xml2)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndProcedure