Chilkat • HOME • Android™ • AutoIt • C • C# • C++ • Chilkat2-Python • CkPython • Classic ASP • DataFlex • Delphi DLL • Go • Java • Node.js • Objective-C • PHP Extension • Perl • PowerBuilder • PowerShell • PureBasic • Ruby • SQL Server • Swift • Tcl • Unicode C • Unicode C++ • VB.NET • VBScript • Visual Basic 6.0 • Visual FoxPro • Xojo Plugin
(PHP Extension) Create JPK VAT metadata XMLDemonstrates how to create the JPK VAT metadata XML (InitUpload) that will be signed using XADES.
<?php // The version number (9_5_0) should match version of the Chilkat extension used, omitting the micro-version number. // For example, if using Chilkat v9.5.0.48, then include as shown here: include("chilkat_9_5_0.php"); // 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> $xml = new CkXml(); $xml->put_Tag('InitUpload'); $xml->AddAttribute('xmlns','http://e-dokumenty.mf.gov.pl'); $xml->UpdateChildContent('DocumentType','JPK'); $xml->UpdateChildContent('Version','01.02.01.20160617'); $xml->UpdateAttrAt('EncryptionKey',true,'algorithm','RSA'); $xml->UpdateAttrAt('EncryptionKey',true,'encoding','Base64'); $xml->UpdateAttrAt('EncryptionKey',true,'mode','ECB'); $xml->UpdateAttrAt('EncryptionKey',true,'padding','PKCS#1'); $xml->UpdateChildContent('EncryptionKey','TO BE DETERMINED'); $xml->UpdateAttrAt('DocumentList|Document|FormCode',true,'schemaVersion','1-1'); $xml->UpdateAttrAt('DocumentList|Document|FormCode',true,'systemCode','JPK_VAT (3)'); $xml->UpdateChildContent('DocumentList|Document|FormCode','JPK_VAT'); $xml->UpdateChildContent('DocumentList|Document|FileName','JPK_VAT_3_v1-1_20181201.xml'); $xml->UpdateChildContent('DocumentList|Document|ContentLength','9999'); $xml->UpdateAttrAt('DocumentList|Document|HashValue',true,'algorithm','SHA-256'); $xml->UpdateAttrAt('DocumentList|Document|HashValue',true,'encoding','Base64'); $xml->UpdateChildContent('DocumentList|Document|HashValue','TO BE DETERMINED'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList',true,'filesNumber','1'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Packaging|SplitZip',true,'mode','zip'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Packaging|SplitZip',true,'type','split'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES',true,'block','16'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES',true,'mode','CBC'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES',true,'padding','PKCS#7'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES',true,'size','256'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES|IV',true,'bytes','16'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|Encryption|AES|IV',true,'encoding','Base64'); $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|Encryption|AES|IV','TO BE DETERMINED'); $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|FileSignature|OrdinalNumber','1'); $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|FileSignature|FileName','JPK_VAT_3_v1-1_20181201-000.xml.zip.aes'); $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|FileSignature|ContentLength','9999'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|FileSignature|HashValue',true,'algorithm','MD5'); $xml->UpdateAttrAt('DocumentList|Document|FileSignatureList|FileSignature|HashValue',true,'encoding','Base64'); $xml->UpdateChildContent('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 $bdXml = new CkBinData(); $success = $bdXml->LoadFile('qa_data/xml_dsig/jpk_vat/JPK_VAT_3_v1-1_20181201-000.xml'); if ($success != true) { print 'Failed to load XML file.' . "\n"; exit; } $xml->UpdateChildContentInt('DocumentList|Document|ContentLength',$bdXml->get_NumBytes()); $crypt = new CkCrypt2(); $crypt->put_HashAlgorithm('sha256'); $crypt->put_EncodingMode('base64'); $xml->UpdateChildContent('DocumentList|Document|HashValue',$crypt->hashBdENC($bdXml)); // ------------------------------------------------------------ // Step 2: Create a Zip archive containing the XML. $zip = new CkZip(); // The filename we pass here doesn't matter because we won't actually be creating a .zip file. $zip->NewZip('anything.zip'); // e is a CkZipEntry $e = $zip->AppendBd('JPK_VAT_3_v1-1_20181201-000.xml',$bdXml); // Write the .zip file to a BinData object. $bdZip = new CkBinData(); $zip->WriteBd($bdZip); // ------------------------------------------------------------ // Step 3: Generate a random 256-bit AES key (32-bytes) $prng = new CkPrng(); $bdAesKey = new CkBinData(); $prng->GenRandomBd(32,$bdAesKey); $ivBytes = $prng->genRandom(16,'base64'); // Store the IV (base64 string) in the XML. $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|Encryption|AES|IV',$ivBytes); // ------------------------------------------------------------ // Step 4: AES encrypt our zip archive (the contents of bdZip) $crypt->put_CipherMode('cbc'); $crypt->put_KeyLength(256); $crypt->put_CryptAlgorithm('aes'); $crypt->put_PaddingScheme(0); $crypt->SetEncodedIV($ivBytes,'base64'); $crypt->SetEncodedKey($bdAesKey->getEncoded('base64'),'base64'); // AES by definition has a block size of 16. $crypt->EncryptBd($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 $success = $bdZip->WriteFile('qa_output/JPK_VAT_3_v1-1_20181201-000.xml.zip.aes'); $xml->UpdateChildContentInt('DocumentList|Document|FileSignatureList|FileSignature|ContentLength',$bdZip->get_NumBytes()); // ------------------------------------------------------------ // Step 4: RSA Encrypt the AES key using the public key certificate provided by the Ministry of Finance $cert = new CkCert(); $success = $cert->LoadFromFile('qa_data/pem/mf_public_rsa.pem'); if ($success != true) { print $cert->lastErrorText() . "\n"; exit; } // pubKey is a CkPublicKey $pubKey = $cert->ExportPublicKey(); $rsa = new CkRsa(); $rsa->ImportPublicKeyObj($pubKey); $rsa->put_EncodingMode('base64'); $rsa->put_LittleEndian(false); // in-place RSA encrypt the contents of bdAesKey. $rsa->EncryptBd($bdAesKey,false); $xml->UpdateChildContent('EncryptionKey',$bdAesKey->getEncoded('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..) $crypt->put_HashAlgorithm('md5'); $xml->UpdateChildContent('DocumentList|Document|FileSignatureList|FileSignature|HashValue',$crypt->hashBdENC($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). $finalXml = $xml->getXml(); print $finalXml . "\n"; $xml->SaveXml('qa_output/jpk_vat.xml'); print 'Finished.' . "\n"; ?> |
© 2000-2025 Chilkat Software, Inc. All Rights Reserved.