Sample code for 30+ languages & platforms
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 memory

Chilkat PureBasic Downloads

PureBasic
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