Guide · iOS · Signing

    iOS code signing explained: certs, profiles & .p12s

    Nathan Claiborne
    Apple's signing model is famously confusing. This guide flattens it: what each file does, where it comes from, and how to assemble the minimum kit needed to ship a build. Pairs well with building an .ipa from GitHub.

    The four artifacts

    • Distribution Certificate — proves your team built the binary. Issued by Apple, valid for one year.
    • Private key — generated locally; only its public half is sent to Apple. Together with the cert it forms a .p12.
    • App ID — a bundle identifier registered to your team (e.g. com.acme.invoices).
    • Provisioning Profile — a signed file that says "this team + this cert + this App ID + these entitlements may ship."

    How they combine

    At build time, Xcode (or Fastlane gym) takes your compiled app, looks up the matching provisioning profile by bundle ID, signs the binary with the private key inside the .p12, and embeds the profile inside the .ipa. Apple's servers later verify the signature chain against the public cert before allowing distribution.

    Exporting a .p12 the right way

    1. In Keychain Access, find your Apple Distribution certificate.
    2. Expand it — confirm the private key appears as a child. If not, you generated the CSR on a different Mac.
    3. Right-click the cert (not the key) → Export → .p12 → set a strong password.

    App Store profile vs Ad Hoc vs Development

    • App Store — required for TestFlight and Store submission. No device list.
    • Ad Hoc — installs on specific registered device UDIDs. Useful for beta clients pre-TestFlight.
    • Development — runs on your registered devices via Xcode. Not for distribution.

    Top 5 errors and how to fix them

    • "No signing certificate 'iOS Distribution' found" — your .p12 wasn't imported into the build keychain, or it lacks the private key.
    • "Provisioning profile doesn't include signing certificate" — regenerate the profile after creating a new cert.
    • "App ID doesn't match" — bundle ID in the Xcode project differs from the profile.
    • "Code signing entitlements file contains entries not in the provisioning profile" — push notifications, App Groups, etc. need to be enabled on the App ID first.
    • Certificate expired — generate a new Distribution cert in Apple Developer, export a new .p12, regenerate the profile.

    Why Corenna validates uploads

    We parse your .p12 and .mobileprovision server-side, extract the team ID, bundle ID, and expiry date, and reject mismatches before you waste 10 minutes on a build that fails at the sign step. It's one of the most common time-savers users mention — see how it works on the Security page.

    Keep reading