~/sajjad $ cat projects/wallet-card
← cd ../projects
Systems
Apple Wallet business card
LiveCert valid to Sep 2027
A signed Apple Wallet pass that sits alongside the payment cards on my phone. Someone scans the code off my screen and lands on this site — no app to install, nothing to hand over, and it works offline once added.
What I built
- Registered a Pass Type ID and generated the CSR and private key from the command line rather than the usual keychain route, which wasn’t available on this machine.
- Assembled the full signing chain — pass certificate, Apple WWDR intermediate, and a CMS signature over a manifest holding a SHA-1 digest of every file in the bundle.
- A build script that rebuilds the manifest, re-signs, zips and refreshes the deploy folder in one command. Design changes cost seconds; the certificate work is never repeated.
- Artwork rendered as a
stripimage on astoreCardpass at 1×, 2× and 3×, so Wallet draws its own scannable code underneath rather than competing with an embedded one — the structure a loyalty card uses. - Back of the pass carries phone, email, portfolio, LinkedIn and education as labelled fields, so the details are readable without scanning anything.
- Hosted on its own site with a
_headersrule setting the pkpass MIME type. Without it the browser downloads a file instead of handing it to Wallet.
The decision that matters
The code’s contents are inside the signature. Point it straight at a profile and changing that target later means rebuilding the pass and re-adding it to every phone holding it.
So it points at a destination I control and can change without touching the pass. The signed artefact never needs revisiting; the certificate runs to September 2027.
What went wrong
- iOS rejected the first passes outright, and Mail wouldn’t open them either — which ruled out the browser and pointed at the signature. The cause was
-noattrstripping the authenticated attributes from the CMS signature. It verifies locally either way, which is exactly why every local check passed. Removing the flag and moving to a SHA-256 digest fixed it. - AirDrop delivers a
.pkpassto Files rather than Wallet, so a working pass looked like a broken one. Email attachment works; so does serving it over HTTPS with the right content type. - A drag-and-drop deploy overwrote an existing site rather than creating a new one. Restored from the previous deploy and separated the two projects permanently.
- Researched Wallet NFC before committing and established it was a dead end — the entitlement is gated to reader protocols, and there is no reader to tap. Ruled out rather than built toward, since the phone-to-phone case is already handled by the operating system for free.