Tcl
Tcl
Create JPK VAT metadata XML
See more RSA Examples
Demonstrates how to create the JPK VAT metadata XML (InitUpload) that will be signed using XADES.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.
# First build an InitUpload XML template
# Use this online tool to generate the code from the sample XML below:
# Generate Code to Create XML
# <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">F9EhKFec...uWqAWUIg==</EncryptionKey>
# <DocumentList>
# <Document>
# <FormCode schemaVersion="1-1" systemCode="JPK_VAT (3)">JPK_VAT</FormCode>
# <FileName>JPK_VAT_3_v1-1_20181201.xml</FileName>
# <ContentLength>8736</ContentLength>
# <HashValue algorithm="SHA-256" encoding="Base64">JFDI1pItwh6dj/Xe1uts/x61qnjZ4DLHpkZMhmf1oKQ=</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">z64oN9zXHt1+S3XACRSCYw==</IV>
# </AES>
# </Encryption>
# <FileSignature>
# <OrdinalNumber>1</OrdinalNumber>
# <FileName>JPK_VAT_3_v1-1_20181201-000.xml.zip.aes</FileName>
# <ContentLength>16</ContentLength>
# <HashValue algorithm="MD5" encoding="Base64">5NX0q1935fvMjLFV7E1yDw==</HashValue>
# </FileSignature>
# </FileSignatureList>
# </Document>
# </DocumentList>
# </InitUpload>
set xml [new_CkXml]
CkXml_put_Tag $xml "InitUpload"
CkXml_AddAttribute $xml "xmlns" "http://e-dokumenty.mf.gov.pl"
CkXml_UpdateChildContent $xml "DocumentType" "JPK"
CkXml_UpdateChildContent $xml "Version" "01.02.01.20160617"
CkXml_UpdateAttrAt $xml "EncryptionKey" 1 "algorithm" "RSA"
CkXml_UpdateAttrAt $xml "EncryptionKey" 1 "encoding" "Base64"
CkXml_UpdateAttrAt $xml "EncryptionKey" 1 "mode" "ECB"
CkXml_UpdateAttrAt $xml "EncryptionKey" 1 "padding" "PKCS#1"
CkXml_UpdateChildContent $xml "EncryptionKey" "TO BE DETERMINED"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FormCode" 1 "schemaVersion" "1-1"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FormCode" 1 "systemCode" "JPK_VAT (3)"
CkXml_UpdateChildContent $xml "DocumentList|Document|FormCode" "JPK_VAT"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileName" "JPK_VAT_3_v1-1_20181201.xml"
CkXml_UpdateChildContent $xml "DocumentList|Document|ContentLength" "9999"
CkXml_UpdateAttrAt $xml "DocumentList|Document|HashValue" 1 "algorithm" "SHA-256"
CkXml_UpdateAttrAt $xml "DocumentList|Document|HashValue" 1 "encoding" "Base64"
CkXml_UpdateChildContent $xml "DocumentList|Document|HashValue" "TO BE DETERMINED"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList" 1 "filesNumber" "1"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Packaging|SplitZip" 1 "mode" "zip"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Packaging|SplitZip" 1 "type" "split"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES" 1 "block" "16"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES" 1 "mode" "CBC"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES" 1 "padding" "PKCS#7"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES" 1 "size" "256"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES|IV" 1 "bytes" "16"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|Encryption|AES|IV" 1 "encoding" "Base64"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|Encryption|AES|IV" "TO BE DETERMINED"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|FileSignature|OrdinalNumber" "1"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|FileSignature|FileName" "JPK_VAT_3_v1-1_20181201-000.xml.zip.aes"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|FileSignature|ContentLength" "9999"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|FileSignature|HashValue" 1 "algorithm" "MD5"
CkXml_UpdateAttrAt $xml "DocumentList|Document|FileSignatureList|FileSignature|HashValue" 1 "encoding" "Base64"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|FileSignature|HashValue" "TO BE DETERMINED"
# ------------------------------------------------------------
# Step 1: Load our JPK_VAT XML and update the DocumentList|Document|HashValue
# and DocumentList|Document|ContentLength
set bdXml [new_CkBinData]
set success [CkBinData_LoadFile $bdXml "qa_data/xml_dsig/jpk_vat/JPK_VAT_3_v1-1_20181201-000.xml"]
if {$success != 1} then {
puts "Failed to load XML file."
delete_CkXml $xml
delete_CkBinData $bdXml
exit
}
CkXml_UpdateChildContentInt $xml "DocumentList|Document|ContentLength" [CkBinData_get_NumBytes $bdXml]
set crypt [new_CkCrypt2]
CkCrypt2_put_HashAlgorithm $crypt "sha256"
CkCrypt2_put_EncodingMode $crypt "base64"
CkXml_UpdateChildContent $xml "DocumentList|Document|HashValue" [CkCrypt2_hashBdENC $crypt $bdXml]
# ------------------------------------------------------------
# Step 2: Create a Zip archive containing the XML.
set zip [new_CkZip]
# The filename we pass here doesn't matter because we won't actually be creating a .zip file.
CkZip_NewZip $zip "anything.zip"
CkZip_AddBd $zip "JPK_VAT_3_v1-1_20181201-000.xml" $bdXml
# Write the .zip file to a BinData object.
set bdZip [new_CkBinData]
CkZip_WriteBd $zip $bdZip
# ------------------------------------------------------------
# Step 3: Generate a random 256-bit AES key (32-bytes)
set prng [new_CkPrng]
set bdAesKey [new_CkBinData]
CkPrng_GenRandomBd $prng 32 $bdAesKey
set ivBytes [CkPrng_genRandom $prng 16 "base64"]
# Store the IV (base64 string) in the XML.
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|Encryption|AES|IV" $ivBytes
# ------------------------------------------------------------
# Step 4: AES encrypt our zip archive (the contents of bdZip)
CkCrypt2_put_CipherMode $crypt "cbc"
CkCrypt2_put_KeyLength $crypt 256
CkCrypt2_put_CryptAlgorithm $crypt "aes"
CkCrypt2_put_PaddingScheme $crypt 0
CkCrypt2_SetEncodedIV $crypt $ivBytes "base64"
CkCrypt2_SetEncodedKey $crypt [CkBinData_getEncoded $bdAesKey "base64"] "base64"
# AES by definition has a block size of 16.
CkCrypt2_EncryptBd $crypt $bdZip
# bdZip now contains the AES encrypted data.
# Note: This is NOT the same as a zip where the contents are AES encrypted.
# In that case, we have an unencrypted zip structure with AES encrypted files within.
# In our case, the entire zip file image is encrypted.
# Save the bdZip to a file. This is what will get sent to e-dokumenty.mf.gov.pl
set success [CkBinData_WriteFile $bdZip "qa_output/JPK_VAT_3_v1-1_20181201-000.xml.zip.aes"]
CkXml_UpdateChildContentInt $xml "DocumentList|Document|FileSignatureList|FileSignature|ContentLength" [CkBinData_get_NumBytes $bdZip]
# ------------------------------------------------------------
# Step 4: RSA Encrypt the AES key using the public key certificate provided by the Ministry of Finance
set cert [new_CkCert]
set success [CkCert_LoadFromFile $cert "qa_data/pem/mf_public_rsa.pem"]
if {$success == 0} then {
puts [CkCert_lastErrorText $cert]
delete_CkXml $xml
delete_CkBinData $bdXml
delete_CkCrypt2 $crypt
delete_CkZip $zip
delete_CkBinData $bdZip
delete_CkPrng $prng
delete_CkBinData $bdAesKey
delete_CkCert $cert
exit
}
set pubKey [new_CkPublicKey]
CkCert_GetPublicKey $cert $pubKey
set rsa [new_CkRsa]
CkRsa_UsePublicKey $rsa $pubKey
CkRsa_put_EncodingMode $rsa "base64"
CkRsa_put_LittleEndian $rsa 0
# in-place RSA encrypt the contents of bdAesKey.
CkRsa_EncryptBd $rsa $bdAesKey 0
CkXml_UpdateChildContent $xml "EncryptionKey" [CkBinData_getEncoded $bdAesKey "base64"]
# Step 5: We forgot to get the MD5 hash of the AES encrypted zip.
# (I'm assuming we need the MD5 of the encrypted zip as opposed to the MD5 of the pre-encrypted zip..)
CkCrypt2_put_HashAlgorithm $crypt "md5"
CkXml_UpdateChildContent $xml "DocumentList|Document|FileSignatureList|FileSignature|HashValue" [CkCrypt2_hashBdENC $crypt $bdZip]
# At this point, the XML is prepared and the AES encrypted image of the zip file is written
# to a file (and also in bdZip).
set finalXml [CkXml_getXml $xml]
puts "$finalXml"
CkXml_SaveXml $xml "qa_output/jpk_vat.xml"
puts "Finished."
delete_CkXml $xml
delete_CkBinData $bdXml
delete_CkCrypt2 $crypt
delete_CkZip $zip
delete_CkBinData $bdZip
delete_CkPrng $prng
delete_CkBinData $bdAesKey
delete_CkCert $cert
delete_CkPublicKey $pubKey
delete_CkRsa $rsa