Signing
How to sign a .pkpass file correctly
A focused guide to Pass Type ID certificates, manifest hashing, detached PKCS#7 signatures, WWDR certificates, and final packaging.
What you’ll leave with
- Sign manifest.json after every other file is final.
- Embed the appropriate WWDR intermediate certificate with the signer certificate.
- Verify certificate identity and the detached signature before shipping.
Prepare the certificate chain
Create a Pass Type ID in the Apple Developer portal and issue a certificate for it. The certificate common name and Pass Type ID extension identify the pass type it may sign, while the organizational unit identifies your Team ID. Those values must agree with passTypeIdentifier and teamIdentifier in pass.json.
Export the private key and certificate into a format your signing environment can use. Protect the private key as a production secret: do not bundle it in an app, commit it to source control, or send it to a browser client.
- Pass Type ID certificate and matching private key
- Current Apple WWDR intermediate certificate
- Unexpired certificates with a chain linked to Apple Root CA
- pass.json identifiers matching the signer identity
Build manifest.json from final bytes
Hash every file that belongs to the pass except manifest.json and signature. Keys are relative archive paths, including localization directories. Values are lowercase hexadecimal SHA-1 digests of the raw file bytes.
Generate the manifest deterministically so the same input files yield the same JSON bytes and signature. Do not rewrite, pretty-print, or normalize manifest.json after signing; the signature covers its exact bytes.
{
"pass.json": "4f5d...9c20",
"icon.png": "a63b...82ea",
"[email protected]": "27aa...dd14",
"en.lproj/pass.strings": "1c01...49f2"
}Create the detached PKCS#7 signature
Create a detached CMS/PKCS#7 signature over manifest.json. The signature payload should include the signer certificate and WWDR intermediate so a verifier can resolve the chain without guessing which intermediate was used.
The resulting binary file is named signature with no extension. A successful signing command is not enough: immediately verify the signature against the manifest and inspect the embedded certificates, signing time, identity fields, and validity dates.
Package and verify the archive
ZIP the pass files themselves, not their parent directory. Preserve case-sensitive filenames and avoid macOS metadata such as __MACOSX and .DS_Store. The final extension is .pkpass, but the internal format remains a ZIP archive.
A complete verifier should recompute every manifest hash, ensure referenced files exist, verify the detached signature, validate certificate dates and the WWDR chain, and compare Team ID and Pass Type ID values with pass.json. Only after those checks pass should the file be distributed.
Put it into practice
Build the JSON, then verify the package.
Use the free browser tools to turn the rules in this guide into a clean starting file and an actionable validation report.
Skip the hand-assembly.
PassMaker does every step on this page on your iPhone — field editor, artwork, manifest, PKCS#7 signing and Add to Wallet — without wiring up a signing environment.
Download on the App StorePrimary references
Related guides
Certificates
WWDR G4 certificate troubleshooting for PKPassUnderstand the Apple WWDR intermediate, identify stale chains, and fix PKPass verification failures involving certificate dates or identity.
7 min readPackaging
PKPass manifest and package structure explainedLearn exactly what belongs inside a .pkpass archive, how manifest hashes work, and why wrapper folders and stale assets break validation.
8 min readTroubleshooting
Fix “Safari cannot download this file” for PKPassDiagnose the common packaging, signature, MIME type, redirect, and certificate problems that prevent Apple Wallet passes from installing.
7 min read