PureBasic
PureBasic
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 PureBasic Downloads
IncludeFile "CkJsonObject.pb"
IncludeFile "CkXmlCertVault.pb"
IncludeFile "CkCrypt2.pb"
IncludeFile "CkZip.pb"
IncludeFile "CkCert.pb"
IncludeFile "CkBinData.pb"
Procedure ChilkatExample()
success.i = 0
; 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.i = CkJsonObject::ckCreate()
If manifest.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
crypt.i = CkCrypt2::ckCreate()
If crypt.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
zip.i = CkZip::ckCreate()
If zip.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkZip::ckNewZip(zip,"notUsedAndNeverCreated.zip")
CkCrypt2::setCkHashAlgorithm(crypt, "sha1")
; Return hashes as lowercase hex.
CkCrypt2::setCkEncodingMode(crypt, "hexlower")
digestStr.s
pngData.i = CkBinData::ckCreate()
If pngData.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
; Assume we load the pngData with bytes for "icon.png" from somewhere, such as a byte array in memory.
CkZip::ckAddBd(zip,"icon.png",pngData)
digestStr = CkCrypt2::ckHashBdENC(crypt,pngData)
CkJsonObject::ckUpdateString(manifest,Chr(34) + "icon.png" + Chr(34),digestStr)
CkBinData::ckClear(pngData)
; Assume we load the pngData with bytes for "icon@2x.png" from somewhere...
CkZip::ckAddBd(zip,"icon@2x.png",pngData)
digestStr = CkCrypt2::ckHashBdENC(crypt,pngData)
CkJsonObject::ckUpdateString(manifest,Chr(34) + "icon@2x.png" + Chr(34),digestStr)
CkBinData::ckClear(pngData)
; Assume we load the pngData with bytes for "logo.png" from somewhere...
CkZip::ckAddBd(zip,"logo.png",pngData)
digestStr = CkCrypt2::ckHashBdENC(crypt,pngData)
CkJsonObject::ckUpdateString(manifest,Chr(34) + "logo.png" + Chr(34),digestStr)
CkBinData::ckClear(pngData)
; Assume we load the pngData with bytes for "logo@2x.png" from somewhere...
CkZip::ckAddBd(zip,"logo@2x.png",pngData)
digestStr = CkCrypt2::ckHashBdENC(crypt,pngData)
CkJsonObject::ckUpdateString(manifest,Chr(34) + "logo@2x.png" + Chr(34),digestStr)
passJson.s = "{ .... }" ; Contains the contents of pass.json
CkZip::ckAddString(zip,"pass.json",passJson,"utf-8")
digestStr = CkCrypt2::ckHashStringENC(crypt,passJson)
CkJsonObject::ckUpdateString(manifest,Chr(34) + "pass.json" + Chr(34),digestStr)
CkZip::ckAddString(zip,"manifest.json",CkJsonObject::ckEmit(manifest),"utf-8")
; Make sure we have the Apple WWDR intermediate certificate available for
; the cert chain in the signature.
certVault.i = CkXmlCertVault::ckCreate()
If certVault.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
appleWwdrCert.i = CkCert::ckCreate()
If appleWwdrCert.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkCert::ckLoadByCommonName(appleWwdrCert,"Apple Worldwide Developer Relations Certification Authority")
If success <> 1
Debug "The Apple WWDR intermediate certificate is not installed."
Debug "It is available at https://developer.apple.com/certificationauthority/AppleWWDRCA.cer"
Debug "You may alternatively load the .cer like this..."
success = CkCert::ckLoadFromFile(appleWwdrCert,"qa_data/certs/AppleWWDRCA.cer")
If success = 0
Debug CkCert::ckLastErrorText(appleWwdrCert)
CkJsonObject::ckDispose(manifest)
CkCrypt2::ckDispose(crypt)
CkZip::ckDispose(zip)
CkBinData::ckDispose(pngData)
CkXmlCertVault::ckDispose(certVault)
CkCert::ckDispose(appleWwdrCert)
ProcedureReturn
EndIf
EndIf
CkXmlCertVault::ckAddCert(certVault,appleWwdrCert)
CkCrypt2::ckUseCertVault(crypt,certVault)
; Use a digital certificate and private key from a PFX
bdPfx.i = CkBinData::ckCreate()
If bdPfx.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
; Assume we loaded a PFX into bdPfx....
pfxPassword.s = "test123"
cert.i = CkCert::ckCreate()
If cert.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkCert::ckLoadPfxBd(cert,bdPfx,pfxPassword)
If success = 0
Debug CkCert::ckLastErrorText(cert)
CkJsonObject::ckDispose(manifest)
CkCrypt2::ckDispose(crypt)
CkZip::ckDispose(zip)
CkBinData::ckDispose(pngData)
CkXmlCertVault::ckDispose(certVault)
CkCert::ckDispose(appleWwdrCert)
CkBinData::ckDispose(bdPfx)
CkCert::ckDispose(cert)
ProcedureReturn
EndIf
; Provide the signing cert (with associated private key).
success = CkCrypt2::ckSetSigningCert(crypt,cert)
If success = 0
Debug CkCrypt2::ckLastErrorText(crypt)
CkJsonObject::ckDispose(manifest)
CkCrypt2::ckDispose(crypt)
CkZip::ckDispose(zip)
CkBinData::ckDispose(pngData)
CkXmlCertVault::ckDispose(certVault)
CkCert::ckDispose(appleWwdrCert)
CkBinData::ckDispose(bdPfx)
CkCert::ckDispose(cert)
ProcedureReturn
EndIf
; 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.i = CkJsonObject::ckCreate()
If jsonSignedAttrs.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkJsonObject::ckUpdateInt(jsonSignedAttrs,"contentType",1)
CkJsonObject::ckUpdateInt(jsonSignedAttrs,"signingTime",1)
CkCrypt2::setCkSigningAttributes(crypt, CkJsonObject::ckEmit(jsonSignedAttrs))
; Sign the manifest JSON to produce a signature
CkCrypt2::setCkEncodingMode(crypt, "base64")
sig.s = CkCrypt2::ckSignStringENC(crypt,CkJsonObject::ckEmit(manifest))
bdSig.i = CkBinData::ckCreate()
If bdSig.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkBinData::ckAppendEncoded(bdSig,sig,"base64")
CkZip::ckAddBd(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.i = CkBinData::ckCreate()
If bdZip.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkZip::ckWriteBd(zip,bdZip)
If success = 0
Debug CkZip::ckLastErrorText(zip)
CkJsonObject::ckDispose(manifest)
CkCrypt2::ckDispose(crypt)
CkZip::ckDispose(zip)
CkBinData::ckDispose(pngData)
CkXmlCertVault::ckDispose(certVault)
CkCert::ckDispose(appleWwdrCert)
CkBinData::ckDispose(bdPfx)
CkCert::ckDispose(cert)
CkJsonObject::ckDispose(jsonSignedAttrs)
CkBinData::ckDispose(bdSig)
CkBinData::ckDispose(bdZip)
ProcedureReturn
EndIf
Debug "Success."
CkJsonObject::ckDispose(manifest)
CkCrypt2::ckDispose(crypt)
CkZip::ckDispose(zip)
CkBinData::ckDispose(pngData)
CkXmlCertVault::ckDispose(certVault)
CkCert::ckDispose(appleWwdrCert)
CkBinData::ckDispose(bdPfx)
CkCert::ckDispose(cert)
CkJsonObject::ckDispose(jsonSignedAttrs)
CkBinData::ckDispose(bdSig)
CkBinData::ckDispose(bdZip)
ProcedureReturn
EndProcedure