Sample code for 30+ languages & platforms
PureBasic

Sign Manifest File to Generate a Passbook .pkpass file

See more Digital Signatures Examples

Demonstrates how to create a Passbook .pkpass archive by creating a signature of a manifest file and then zipping to a .pkpass archive.

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

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkJsonObject.pb"
IncludeFile "CkXmlCertVault.pb"
IncludeFile "CkCrypt2.pb"
IncludeFile "CkZip.pb"
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkCert.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    ; ---------------------------------------------------------------------------------------------
    ; Note: Chilkat also has the capability to do everything in-memory (no files would be involved).  
    ; See this example:  Sign Manifest File to Generate a Passbook .pkpass in Memory
    ; ---------------------------------------------------------------------------------------------

    ; 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,"qa_data/p7s/pass-wallet/example.pkpass")
    ; Set the AppendFromDir property to prevent that relative paths from being stored in the .pkpass archive.
    CkZip::setCkAppendFromDir(zip, "qa_data/p7s/pass-wallet/")

    CkCrypt2::setCkHashAlgorithm(crypt, "sha1")
    ; Return hashes as lowercase hex.
    CkCrypt2::setCkEncodingMode(crypt, "hexlower")

    fileHash.s
    filePath.s
    filePath = "qa_data/p7s/pass-wallet/icon.png"
    fileHash = CkCrypt2::ckHashFileENC(crypt,filePath)
    CkZip::ckAddFile(zip,"icon.png",0)
    CkJsonObject::ckUpdateString(manifest,Chr(34) + "icon.png" + Chr(34),fileHash)

    filePath = "qa_data/p7s/pass-wallet/icon@2x.png"
    fileHash = CkCrypt2::ckHashFileENC(crypt,filePath)
    CkZip::ckAddFile(zip,"icon@2x.png",0)
    CkJsonObject::ckUpdateString(manifest,Chr(34) + "icon@2x.png" + Chr(34),fileHash)

    filePath = "qa_data/p7s/pass-wallet/logo.png"
    fileHash = CkCrypt2::ckHashFileENC(crypt,filePath)
    CkZip::ckAddFile(zip,"logo.png",0)
    CkJsonObject::ckUpdateString(manifest,Chr(34) + "logo.png" + Chr(34),fileHash)

    filePath = "qa_data/p7s/pass-wallet/logo@2x.png"
    fileHash = CkCrypt2::ckHashFileENC(crypt,filePath)
    CkZip::ckAddFile(zip,"logo@2x.png",0)
    CkJsonObject::ckUpdateString(manifest,Chr(34) + "logo@2x.png" + Chr(34),fileHash)

    filePath = "qa_data/p7s/pass-wallet/pass.json"
    fileHash = CkCrypt2::ckHashFileENC(crypt,filePath)
    CkZip::ckAddFile(zip,"pass.json",0)
    CkJsonObject::ckUpdateString(manifest,Chr(34) + "pass.json" + Chr(34),fileHash)

    sbJson.i = CkStringBuilder::ckCreate()
    If sbJson.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkJsonObject::ckEmitSb(manifest,sbJson)
    manifestPath.s = "qa_data/p7s/pass-wallet/manifest.json"
    CkStringBuilder::ckWriteFile(sbJson,manifestPath,"utf-8",0)
    CkZip::ckAddFile(zip,"manifest.json",0)

    ; 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)
            CkStringBuilder::ckDispose(sbJson)
            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 file (.pfx or .p12).
    pfxPath.s = "qa_data/pfx/cert_test123.pfx"
    pfxPassword.s = "test123"

    cert.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkCert::ckLoadPfxFile(cert,pfxPath,pfxPassword)
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkJsonObject::ckDispose(manifest)
        CkCrypt2::ckDispose(crypt)
        CkZip::ckDispose(zip)
        CkStringBuilder::ckDispose(sbJson)
        CkXmlCertVault::ckDispose(certVault)
        CkCert::ckDispose(appleWwdrCert)
        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)
        CkStringBuilder::ckDispose(sbJson)
        CkXmlCertVault::ckDispose(certVault)
        CkCert::ckDispose(appleWwdrCert)
        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 file to produce a file named "signature".
    sigPath.s = "qa_data/p7s/pass-wallet/signature"

    ; Create the "signature" file.
    success = CkCrypt2::ckCreateP7S(crypt,manifestPath,sigPath)
    If success = 0
        Debug CkCrypt2::ckLastErrorText(crypt)
        CkJsonObject::ckDispose(manifest)
        CkCrypt2::ckDispose(crypt)
        CkZip::ckDispose(zip)
        CkStringBuilder::ckDispose(sbJson)
        CkXmlCertVault::ckDispose(certVault)
        CkCert::ckDispose(appleWwdrCert)
        CkCert::ckDispose(cert)
        CkJsonObject::ckDispose(jsonSignedAttrs)
        ProcedureReturn
    EndIf

    CkZip::ckAddFile(zip,"signature",0)

    ; ---------------------------------------------------------------------------------------------
    ; 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).
    success = CkZip::ckWriteZipAndClose(zip)
    If success = 0
        Debug CkZip::ckLastErrorText(zip)
        CkJsonObject::ckDispose(manifest)
        CkCrypt2::ckDispose(crypt)
        CkZip::ckDispose(zip)
        CkStringBuilder::ckDispose(sbJson)
        CkXmlCertVault::ckDispose(certVault)
        CkCert::ckDispose(appleWwdrCert)
        CkCert::ckDispose(cert)
        CkJsonObject::ckDispose(jsonSignedAttrs)
        ProcedureReturn
    EndIf

    Debug "Success."


    CkJsonObject::ckDispose(manifest)
    CkCrypt2::ckDispose(crypt)
    CkZip::ckDispose(zip)
    CkStringBuilder::ckDispose(sbJson)
    CkXmlCertVault::ckDispose(certVault)
    CkCert::ckDispose(appleWwdrCert)
    CkCert::ckDispose(cert)
    CkJsonObject::ckDispose(jsonSignedAttrs)


    ProcedureReturn
EndProcedure