C
C
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 C Downloads
#include <C_CkJsonObject.h>
#include <C_CkCrypt2.h>
#include <C_CkZip.h>
#include <C_CkBinData.h>
#include <C_CkXmlCertVault.h>
#include <C_CkCert.h>
void ChilkatSample(void)
{
BOOL success;
HCkJsonObject manifest;
HCkCrypt2 crypt;
HCkZip zip;
const char *digestStr;
HCkBinData pngData;
const char *passJson;
HCkXmlCertVault certVault;
HCkCert appleWwdrCert;
HCkBinData bdPfx;
const char *pfxPassword;
HCkCert cert;
HCkJsonObject jsonSignedAttrs;
const char *sig;
HCkBinData bdSig;
HCkBinData bdZip;
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) {
printf("The Apple WWDR intermediate certificate is not installed.\n");
printf("It is available at https://developer.apple.com/certificationauthority/AppleWWDRCA.cer\n");
printf("You may alternatively load the .cer like this...\n");
success = CkCert_LoadFromFile(appleWwdrCert,"qa_data/certs/AppleWWDRCA.cer");
if (success == FALSE) {
printf("%s\n",CkCert_lastErrorText(appleWwdrCert));
CkJsonObject_Dispose(manifest);
CkCrypt2_Dispose(crypt);
CkZip_Dispose(zip);
CkBinData_Dispose(pngData);
CkXmlCertVault_Dispose(certVault);
CkCert_Dispose(appleWwdrCert);
return;
}
}
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) {
printf("%s\n",CkCert_lastErrorText(cert));
CkJsonObject_Dispose(manifest);
CkCrypt2_Dispose(crypt);
CkZip_Dispose(zip);
CkBinData_Dispose(pngData);
CkXmlCertVault_Dispose(certVault);
CkCert_Dispose(appleWwdrCert);
CkBinData_Dispose(bdPfx);
CkCert_Dispose(cert);
return;
}
// Provide the signing cert (with associated private key).
success = CkCrypt2_SetSigningCert(crypt,cert);
if (success == FALSE) {
printf("%s\n",CkCrypt2_lastErrorText(crypt));
CkJsonObject_Dispose(manifest);
CkCrypt2_Dispose(crypt);
CkZip_Dispose(zip);
CkBinData_Dispose(pngData);
CkXmlCertVault_Dispose(certVault);
CkCert_Dispose(appleWwdrCert);
CkBinData_Dispose(bdPfx);
CkCert_Dispose(cert);
return;
}
// 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) {
printf("%s\n",CkZip_lastErrorText(zip));
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);
return;
}
printf("Success.\n");
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);
}