Delphi DLL
Delphi DLL
Sign Manifest File to Generate a Passbook .pkpass in Memory
Demonstrates how to create a Passbook .pkpass archive by creating a signature of a manifest file and then zipping to a .pkpass archive in memoryChilkat Delphi DLL Downloads
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Zip, XmlCertVault, JsonObject, Cert, Crypt2, BinData;
...
procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
manifest: HCkJsonObject;
crypt: HCkCrypt2;
zip: HCkZip;
digestStr: PWideChar;
pngData: HCkBinData;
passJson: PWideChar;
certVault: HCkXmlCertVault;
appleWwdrCert: HCkCert;
bdPfx: HCkBinData;
pfxPassword: PWideChar;
cert: HCkCert;
jsonSignedAttrs: HCkJsonObject;
sig: PWideChar;
bdSig: HCkBinData;
bdZip: HCkBinData;
begin
success := False;
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// ---------------------------------------------------------------------------------------------
// This example is the same as Sign Manifest File to Generate a Passbook .pkpass file
// except everything happens in memory (no input files, no output files)
// ---------------------------------------------------------------------------------------------
// First create the manifest.json
manifest := CkJsonObject_Create();
crypt := CkCrypt2_Create();
zip := CkZip_Create();
CkZip_NewZip(zip,'notUsedAndNeverCreated.zip');
CkCrypt2_putHashAlgorithm(crypt,'sha1');
// Return hashes as lowercase hex.
CkCrypt2_putEncodingMode(crypt,'hexlower');
pngData := CkBinData_Create();
// Assume we load the pngData with bytes for "icon.png" from somewhere, such as a byte array in memory.
CkZip_AddBd(zip,'icon.png',pngData);
digestStr := CkCrypt2__hashBdENC(crypt,pngData);
CkJsonObject_UpdateString(manifest,'"icon.png"',digestStr);
CkBinData_Clear(pngData);
// Assume we load the pngData with bytes for "icon@2x.png" from somewhere...
CkZip_AddBd(zip,'icon@2x.png',pngData);
digestStr := CkCrypt2__hashBdENC(crypt,pngData);
CkJsonObject_UpdateString(manifest,'"icon@2x.png"',digestStr);
CkBinData_Clear(pngData);
// Assume we load the pngData with bytes for "logo.png" from somewhere...
CkZip_AddBd(zip,'logo.png',pngData);
digestStr := CkCrypt2__hashBdENC(crypt,pngData);
CkJsonObject_UpdateString(manifest,'"logo.png"',digestStr);
CkBinData_Clear(pngData);
// Assume we load the pngData with bytes for "logo@2x.png" from somewhere...
CkZip_AddBd(zip,'logo@2x.png',pngData);
digestStr := CkCrypt2__hashBdENC(crypt,pngData);
CkJsonObject_UpdateString(manifest,'"logo@2x.png"',digestStr);
passJson := '{ .... }';// Contains the contents of pass.json
CkZip_AddString(zip,'pass.json',passJson,'utf-8');
digestStr := CkCrypt2__hashStringENC(crypt,passJson);
CkJsonObject_UpdateString(manifest,'"pass.json"',digestStr);
CkZip_AddString(zip,'manifest.json',CkJsonObject__emit(manifest),'utf-8');
// Make sure we have the Apple WWDR intermediate certificate available for
// the cert chain in the signature.
certVault := CkXmlCertVault_Create();
appleWwdrCert := CkCert_Create();
success := CkCert_LoadByCommonName(appleWwdrCert,'Apple Worldwide Developer Relations Certification Authority');
if (success <> True) then
begin
Memo1.Lines.Add('The Apple WWDR intermediate certificate is not installed.');
Memo1.Lines.Add('It is available at https://developer.apple.com/certificationauthority/AppleWWDRCA.cer');
Memo1.Lines.Add('You may alternatively load the .cer like this...');
success := CkCert_LoadFromFile(appleWwdrCert,'qa_data/certs/AppleWWDRCA.cer');
if (success = False) then
begin
Memo1.Lines.Add(CkCert__lastErrorText(appleWwdrCert));
Exit;
end;
end;
CkXmlCertVault_AddCert(certVault,appleWwdrCert);
CkCrypt2_UseCertVault(crypt,certVault);
// Use a digital certificate and private key from a PFX
bdPfx := CkBinData_Create();
// Assume we loaded a PFX into bdPfx....
pfxPassword := 'test123';
cert := CkCert_Create();
success := CkCert_LoadPfxBd(cert,bdPfx,pfxPassword);
if (success = False) then
begin
Memo1.Lines.Add(CkCert__lastErrorText(cert));
Exit;
end;
// Provide the signing cert (with associated private key).
success := CkCrypt2_SetSigningCert(crypt,cert);
if (success = False) then
begin
Memo1.Lines.Add(CkCrypt2__lastErrorText(crypt));
Exit;
end;
// Specify the signed attributes to be included.
// (These attributes appear to not be necessary, but we're including
// them just in case they become necessary in the future.)
jsonSignedAttrs := CkJsonObject_Create();
CkJsonObject_UpdateInt(jsonSignedAttrs,'contentType',1);
CkJsonObject_UpdateInt(jsonSignedAttrs,'signingTime',1);
CkCrypt2_putSigningAttributes(crypt,CkJsonObject__emit(jsonSignedAttrs));
// Sign the manifest JSON to produce a signature
CkCrypt2_putEncodingMode(crypt,'base64');
sig := CkCrypt2__signStringENC(crypt,CkJsonObject__emit(manifest));
bdSig := CkBinData_Create();
CkBinData_AppendEncoded(bdSig,sig,'base64');
CkZip_AddBd(zip,'signature',bdSig);
// ---------------------------------------------------------------------------------------------
// Note: Chilkat also has the capability to do everything in-memory (no files would be involved).
// If this is of interest, please send email to support@chilkatsoft.com
// ---------------------------------------------------------------------------------------------
// Create the .pkipass archive (which is a .zip archive containing the required files).
// the .zip is written to bdZip
bdZip := CkBinData_Create();
success := CkZip_WriteBd(zip,bdZip);
if (success = False) then
begin
Memo1.Lines.Add(CkZip__lastErrorText(zip));
Exit;
end;
Memo1.Lines.Add('Success.');
CkJsonObject_Dispose(manifest);
CkCrypt2_Dispose(crypt);
CkZip_Dispose(zip);
CkBinData_Dispose(pngData);
CkXmlCertVault_Dispose(certVault);
CkCert_Dispose(appleWwdrCert);
CkBinData_Dispose(bdPfx);
CkCert_Dispose(cert);
CkJsonObject_Dispose(jsonSignedAttrs);
CkBinData_Dispose(bdSig);
CkBinData_Dispose(bdZip);
end;