Tcl
Tcl
UBL XAdES Enveloped Signature
See more XAdES Examples
Demonstrates how to create a UBL XAdES enveloped signature.Chilkat Tcl Downloads
load ./chilkat.dll
set success 0
# This example requires the Chilkat API to have been previously unlocked.
# See Global Unlock Sample for sample code.
set success 1
#
# The following code creates the XML document to be signed.
# (It is also possible to simply load the XML into the Chilkat XML object by calling the LoadXml method.)
# A sample (already signed) of this XML is available here: External link: credit-note-en16931-xades-signed.xml
# Also, you may use this online tool to generate code from sample XML:
# Generate Code to Create XML
set xmlToSign [new_CkXml]
CkXml_put_Tag $xmlToSign "CreditNote"
CkXml_AddAttribute $xmlToSign "xmlns" "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
CkXml_AddAttribute $xmlToSign "xmlns:cac" "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
CkXml_AddAttribute $xmlToSign "xmlns:cbc" "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
CkXml_AddAttribute $xmlToSign "xmlns:ext" "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
CkXml_UpdateAttrAt $xmlToSign "ext:UBLExtensions|ext:UBLExtension" 1 "xmlns:sac" "urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2"
CkXml_UpdateAttrAt $xmlToSign "ext:UBLExtensions|ext:UBLExtension" 1 "xmlns:sig" "urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2"
CkXml_UpdateChildContent $xmlToSign "ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation" ""
CkXml_UpdateChildContent $xmlToSign "cbc:CustomizationID" "urn:cen.eu:en16931:2017"
CkXml_UpdateChildContent $xmlToSign "cbc:ProfileID" "P1"
CkXml_UpdateChildContent $xmlToSign "cbc:ID" "c2ad1540-cf12-4e83-b47c-906aac70242e"
CkXml_UpdateChildContent $xmlToSign "cbc:IssueDate" "2009-12-15"
CkXml_UpdateAttrAt $xmlToSign "cbc:Note" 1 "languageID" "en"
CkXml_UpdateChildContent $xmlToSign "cbc:Note" "Ordered in our booth at the convention."
CkXml_UpdateAttrAt $xmlToSign "cbc:DocumentCurrencyCode" 1 "listAgencyID" "6"
CkXml_UpdateAttrAt $xmlToSign "cbc:DocumentCurrencyCode" 1 "listID" "ISO 4217 Alpha"
CkXml_UpdateChildContent $xmlToSign "cbc:DocumentCurrencyCode" "HRK"
CkXml_UpdateChildContent $xmlToSign "cbc:AccountingCost" "Project cost code 123"
CkXml_UpdateChildContent $xmlToSign "cac:InvoicePeriod|cbc:StartDate" "2009-11-01"
CkXml_UpdateChildContent $xmlToSign "cac:InvoicePeriod|cbc:EndDate" "2009-11-30"
CkXml_UpdateChildContent $xmlToSign "cac:OrderReference|cbc:ID" "123"
CkXml_UpdateChildContent $xmlToSign "cac:ContractDocumentReference|cbc:ID" "Contract321"
CkXml_UpdateChildContent $xmlToSign "cac:ContractDocumentReference|cbc:DocumentType" "Framework agreement"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference|cbc:ID" "Doc1"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference|cbc:DocumentType" "Timesheet"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference|cac:Attachment|cac:ExternalReference|cbc:URI" "http://www.suppliersite.eu/sheet001.html"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference[1]|cbc:ID" "Doc2"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference[1]|cbc:DocumentType" "Drawing"
CkXml_UpdateAttrAt $xmlToSign "cac:AdditionalDocumentReference[1]|cac:Attachment|cbc:EmbeddedDocumentBinaryObject" 1 "mimeCode" "application/pdf"
CkXml_UpdateChildContent $xmlToSign "cac:AdditionalDocumentReference[1]|cac:Attachment|cbc:EmbeddedDocumentBinaryObject" "UjBsR09EbGhjZ0dTQUxNQUFBUUNBRU1tQ1p0dU1GUXhEUzhi"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PartyIdentification|cbc:ID" "9934:18683136487::HR99:276"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PostalAddress|cbc:StreetName" "KATANCICEVA"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PostalAddress|cbc:CityName" "ZAGREB"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PostalAddress|cbc:PostalZone" "10000"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PostalAddress|cac:Country|cbc:IdentificationCode" "HR"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PartyTaxScheme|cbc:CompanyID" "HR18683136487"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PartyTaxScheme|cac:TaxScheme|cbc:ID" "FRE"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:PartyLegalEntity|cbc:RegistrationName" "MINISTARSTVO FINANCIJA"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:Contact|cbc:Name" "JURAJ MARKOVIC"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingSupplierParty|cac:Party|cac:Contact|cbc:ElectronicMail" "juraj.markovic@fina.hr"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PartyIdentification|cbc:ID" "9934:49811265576::HR99:NOVO1"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PostalAddress|cbc:StreetName" "GETALDICEVA 4"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PostalAddress|cbc:CityName" "ZAGREB"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PostalAddress|cbc:PostalZone" "10000"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PostalAddress|cac:Country|cbc:IdentificationCode" "HR"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PartyTaxScheme|cbc:CompanyID" "HR49811265576"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PartyTaxScheme|cac:TaxScheme|cbc:ID" "VAT"
CkXml_UpdateChildContent $xmlToSign "cac:AccountingCustomerParty|cac:Party|cac:PartyLegalEntity|cbc:RegistrationName" "NOVO1"
CkXml_UpdateChildContent $xmlToSign "cac:Delivery|cac:DeliveryLocation|cac:Address|cac:Country|cbc:IdentificationCode" "HR"
CkXml_UpdateChildContent $xmlToSign "cac:PaymentMeans|cbc:PaymentMeansCode" "30"
CkXml_UpdateChildContent $xmlToSign "cac:PaymentMeans|cbc:InstructionNote" "Neki opis placanja"
CkXml_UpdateChildContent $xmlToSign "cac:PaymentMeans|cbc:PaymentID" "HR00 12456"
CkXml_UpdateChildContent $xmlToSign "cac:PaymentMeans|cac:PayeeFinancialAccount|cbc:ID" "HR1210010051863000160"
CkXml_UpdateChildContent $xmlToSign "cac:PaymentTerms|cbc:Note" "Neki uvjeti placanja"
CkXml_UpdateAttrAt $xmlToSign "cac:TaxTotal|cbc:TaxAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cbc:TaxAmount" "25.00"
CkXml_UpdateAttrAt $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cbc:TaxableAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cbc:TaxableAmount" "100.00"
CkXml_UpdateAttrAt $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cbc:TaxAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cbc:TaxAmount" "25.00"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cac:TaxCategory|cbc:ID" "S"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cac:TaxCategory|cbc:Percent" "25"
CkXml_UpdateChildContent $xmlToSign "cac:TaxTotal|cac:TaxSubtotal|cac:TaxCategory|cac:TaxScheme|cbc:ID" "VAT"
CkXml_UpdateAttrAt $xmlToSign "cac:LegalMonetaryTotal|cbc:LineExtensionAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:LegalMonetaryTotal|cbc:LineExtensionAmount" "100.00"
CkXml_UpdateAttrAt $xmlToSign "cac:LegalMonetaryTotal|cbc:TaxExclusiveAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:LegalMonetaryTotal|cbc:TaxExclusiveAmount" "100.00"
CkXml_UpdateAttrAt $xmlToSign "cac:LegalMonetaryTotal|cbc:TaxInclusiveAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:LegalMonetaryTotal|cbc:TaxInclusiveAmount" "125.00"
CkXml_UpdateAttrAt $xmlToSign "cac:LegalMonetaryTotal|cbc:PayableAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:LegalMonetaryTotal|cbc:PayableAmount" "125.00"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cbc:ID" "1"
CkXml_UpdateAttrAt $xmlToSign "cac:CreditNoteLine|cbc:CreditedQuantity" 1 "unitCode" "H87"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cbc:CreditedQuantity" "1.000"
CkXml_UpdateAttrAt $xmlToSign "cac:CreditNoteLine|cbc:LineExtensionAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cbc:LineExtensionAmount" "100.00"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cbc:Description" "Neki detaljniji opis proizvoda ide ovdje"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cbc:Name" "Neki proizvod"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:OriginCountry|cbc:IdentificationCode" "HR"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:ClassifiedTaxCategory|cbc:ID" "S"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:ClassifiedTaxCategory|cbc:Percent" "25"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:ClassifiedTaxCategory|cac:TaxScheme|cbc:ID" "VAT"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:AdditionalItemProperty|cbc:Name" "Boja"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:AdditionalItemProperty|cbc:Value" "Plava"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:AdditionalItemProperty[1]|cbc:Name" "Masa"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Item|cac:AdditionalItemProperty[1]|cbc:Value" "1,2 Kg"
CkXml_UpdateAttrAt $xmlToSign "cac:CreditNoteLine|cac:Price|cbc:PriceAmount" 1 "currencyID" "HRK"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Price|cbc:PriceAmount" "100.000000"
CkXml_UpdateAttrAt $xmlToSign "cac:CreditNoteLine|cac:Price|cbc:BaseQuantity" 1 "unitCode" "H87"
CkXml_UpdateChildContent $xmlToSign "cac:CreditNoteLine|cac:Price|cbc:BaseQuantity" "1.000"
# Use this online tool to generate XAdES code from a sample signed XML:
# Generate Code to Creaet XAdES from Sample XAdES
# The following code was generated by the online tool.
set gen [new_CkXmlDSigGen]
CkXmlDSigGen_put_SigLocation $gen "CreditNote|ext:UBLExtensions|ext:UBLExtension|ext:ExtensionContent|sig:UBLDocumentSignatures|sac:SignatureInformation"
CkXmlDSigGen_put_SigLocationMod $gen 0
CkXmlDSigGen_put_SigId $gen "Signature-7f4c4719515a4a0a8ce4d1b983a2ec69"
CkXmlDSigGen_put_SigNamespacePrefix $gen ""
CkXmlDSigGen_put_SigNamespaceUri $gen "http://www.w3.org/2000/09/xmldsig#"
CkXmlDSigGen_put_SignedInfoCanonAlg $gen "C14N"
CkXmlDSigGen_put_SignedInfoDigestMethod $gen "sha256"
# Create an Object to be added to the Signature.
set object1 [new_CkXml]
CkXml_put_Tag $object1 "xades:QualifyingProperties"
CkXml_AddAttribute $object1 "xmlns:ds" "http://www.w3.org/2000/09/xmldsig#"
CkXml_AddAttribute $object1 "xmlns:xades" "http://uri.etsi.org/01903/v1.3.2#"
CkXml_AddAttribute $object1 "Target" "#Signature-7f4c4719515a4a0a8ce4d1b983a2ec69"
CkXml_UpdateAttrAt $object1 "xades:SignedProperties" 1 "Id" "SignedProperties-6573207f4ad64b49b0310f7a9e2dfadc"
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime" "TO BE GENERATED BY CHILKAT"
# Note: It may be that http://www.w3.org/2001/04/xmlenc#sha256 is needed in the following line instead of http://www.w3.org/2000/09/xmldsig#sha1
CkXml_UpdateAttrAt $object1 "xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestMethod" 1 "Algorithm" "http://www.w3.org/2000/09/xmldsig#sha1"
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestValue" "TO BE GENERATED BY CHILKAT"
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:IssuerSerialV2" "TO BE GENERATED BY CHILKAT"
CkXml_UpdateAttrAt $object1 "xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat" 1 "ObjectReference" ""
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:Description" "document"
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:MimeType" "application/xml"
CkXml_UpdateChildContent $object1 "xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:Encoding" "UTF-8"
CkXmlDSigGen_AddObject $gen "" [CkXml_getXml $object1] "" ""
# -------- Reference 1 --------
CkXmlDSigGen_AddSameDocRef $gen "" "sha256" "" "" ""
# -------- Reference 2 --------
CkXmlDSigGen_AddObjectRef $gen "SignedProperties-6573207f4ad64b49b0310f7a9e2dfadc" "sha256" "" "" "http://uri.etsi.org/01903#SignedProperties"
# Provide a certificate + private key. (PFX password is test123)
set cert [new_CkCert]
set success [CkCert_LoadPfxFile $cert "qa_data/pfx/cert_test123.pfx" "test123"]
if {$success != 1} then {
puts [CkCert_lastErrorText $cert]
delete_CkXml $xmlToSign
delete_CkXmlDSigGen $gen
delete_CkXml $object1
delete_CkCert $cert
exit
}
CkXmlDSigGen_SetX509Cert $gen $cert 1
CkXmlDSigGen_put_KeyInfoType $gen "X509Data+KeyValue"
CkXmlDSigGen_put_X509Type $gen "IssuerSerial,SubjectName,SKI,Certificate"
# Load XML to be signed...
set sbXml [new_CkStringBuilder]
CkXml_GetXmlSb $xmlToSign $sbXml
# Adding the "UBLDocumentSignatures" behavior causes the following Transform to be used for the
# first Reference:
# <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"><XPath>count(ancestor-or-self::sig:UBLDocumentSignatures | here()/ancestor::sig:UBLDocumentSignatures[1]) > count(ancestor-or-self::sig:UBLDocumentSignatures)</XPath></Transform>
CkXmlDSigGen_put_Behaviors $gen "IndentedSignature,UBLDocumentSignatures"
# Sign the XML...
set success [CkXmlDSigGen_CreateXmlDSigSb $gen $sbXml]
if {$success != 1} then {
puts [CkXmlDSigGen_lastErrorText $gen]
delete_CkXml $xmlToSign
delete_CkXmlDSigGen $gen
delete_CkXml $object1
delete_CkCert $cert
delete_CkStringBuilder $sbXml
exit
}
# -----------------------------------------------
# Save the signed XML to a file.
set success [CkStringBuilder_WriteFile $sbXml "qa_output/signedXml.xml" "utf-8" 0]
puts [CkStringBuilder_getAsString $sbXml]
# ----------------------------------------
# Verify the signature we just produced...
set verifier [new_CkXmlDSig]
set success [CkXmlDSig_LoadSignatureSb $verifier $sbXml]
if {$success != 1} then {
puts [CkXmlDSig_lastErrorText $verifier]
delete_CkXml $xmlToSign
delete_CkXmlDSigGen $gen
delete_CkXml $object1
delete_CkCert $cert
delete_CkStringBuilder $sbXml
delete_CkXmlDSig $verifier
exit
}
# We should have just one signature..
set numSigs [CkXmlDSig_get_NumSignatures $verifier]
set verifyIdx 0
while {$verifyIdx < $numSigs} {
CkXmlDSig_put_Selector $verifier $verifyIdx
set verified [CkXmlDSig_VerifySignature $verifier 1]
if {$verified != 1} then {
puts [CkXmlDSig_lastErrorText $verifier]
delete_CkXml $xmlToSign
delete_CkXmlDSigGen $gen
delete_CkXml $object1
delete_CkCert $cert
delete_CkStringBuilder $sbXml
delete_CkXmlDSig $verifier
exit
}
set verifyIdx [expr $verifyIdx + 1]
}
puts "The signature was successfully verified."
delete_CkXml $xmlToSign
delete_CkXmlDSigGen $gen
delete_CkXml $object1
delete_CkCert $cert
delete_CkStringBuilder $sbXml
delete_CkXmlDSig $verifier