Signing a pass.
From a Pass Type ID to a .pkpass Wallet opens, with the commands, and the faults that stop it.
A pass is signed by hashing every file into manifest.json and signing that manifest with a Pass Type ID certificate and Apple’s WWDR intermediate. Wallet refuses the pass if any file changed afterwards or either certificate is missing or expired.
- Certificate
- A Pass Type ID certificate from your Apple Developer account.
- Intermediate
- Apple’s WWDR certificate, included in the signature.
- Signature
- A detached PKCS#7 over manifest.json, in DER.
Seven steps to a signed pass.
- 01
Create a Pass Type ID
In your Apple Developer account: Certificates, Identifiers & Profiles, Identifiers, then Pass Type IDs. It looks likepass.com.example.card. - 02
Make a signing request
openssl req -new -newkey rsa:2048 -nodes -keyout pass.key -out pass.csr \ -subj "/emailAddress=you@example.com/CN=Example Pass/C=GB" - 03
Upload it and download the certificate
Under Certificates, create a Pass Type ID Certificate for that ID, uploadpass.csr, and downloadpass.cer. Convert it:openssl x509 -inform der -in pass.cer -out pass.pem - 04
Get the WWDR intermediate
From Apple’s certificate authority page (checked 24 September 2026):curl -sO https://www.apple.com/certificateauthority/AppleWWDRCAG4.cer openssl x509 -inform der -in AppleWWDRCAG4.cer -out wwdr.pem - 05
Write manifest.json
A JSON object of every file in the pass and its SHA-1, for example withshasum -a 1 pass.json icon.png …. Every file, and nothing else: not manifest.json, not signature. - 06
Sign the manifest
openssl smime -binary -sign -certfile wwdr.pem -signer pass.pem -inkey pass.key \ -in manifest.json -out signature -outform DER - 07
Zip it and serve it
Serve it aszip -q my.pkpass pass.json manifest.json signature *.pngapplication/vnd.apple.pkpass.
Why it will not open.
| Fault | Fix | Caught by the viewer |
|---|---|---|
| The Pass Type ID certificate has expired | Create a new certificate for the same Pass Type ID and re-sign. Passes already issued keep working; new ones need the new certificate. | Yes |
| The WWDR intermediate is missing from the signature | Pass it to openssl with -certfile. Without it Wallet cannot build the chain. | Yes |
| passTypeIdentifier is not the certificate’s | Use the exact Pass Type ID the certificate was issued for. | Yes |
| teamIdentifier is not the certificate’s | Use the team ID in the certificate’s OU field. | Yes |
| A file changed after signing | Regenerate manifest.json and the signature after the last edit to any file. | Yes |
| There is no icon.png | Add icon.png (and @2x, @3x) before building the manifest. | Yes |
| The server sends the wrong content type | Serve .pkpass as application/vnd.apple.pkpass, or Safari downloads it instead of opening Wallet. | No (a server header) |
The viewer reads the signature; it does not verify the chain against Apple’s root.
Signing questions.
Which WWDR certificate do I need?
The one Apple’s certificate authority page names for Pass Type ID certificates on the day you sign. As checked on 24 September 2026, that is the G4 intermediate.
Do passes stop working when my certificate expires?
Passes already in Wallet keep displaying. New passes and updates need a valid certificate.
How do I see what is wrong with mine?
Open it in the .pkpass viewer: it reads the signer, its expiry and the WWDR intermediate, and checks the manifest, in your browser.