Why iOS 15 Rejects Your Enterprise IPA and How Re‑signing Fixes It
The article explains the iOS code‑signing verification mechanism, why enterprise IPAs built for iOS 15 fail with a signature‑version error, and provides a step‑by‑step guide to re‑sign the package using newer signature formats, along with a deep dive into certificates, provisioning profiles, entitlements and the underlying cryptographic concepts.
iOS signing verification is the foundation of Apple’s ecosystem security. This article first introduces digital signatures and certificates, then details the generation and installation of Apple developer certificates, and finally explains the iOS signing verification flow and the key information involved.
Background and problem
After the iOS 15 beta release, QA engineers found that enterprise IPAs produced by the CI pipeline could not be installed on iOS 15 devices, showing the error “The code signature version is no longer supported.” By inspecting the IPA with codesign, the CodeDirectory version was found to be v=20400. iOS 14 accepts this version, but iOS 15 enforces a newer format.
Solution
Re‑signing the IPA with a newer signature format on macOS 11.5.2 or macOS 12 beta resolves the issue, allowing installation on iOS 15 devices.
Fundamental concepts
Digital signatures ensure integrity, authenticity and non‑repudiation. Symmetric encryption (DES, 3DES, AES) uses the same key for encryption and decryption, while asymmetric encryption (RSA) uses a public key for encryption and a private key for decryption. Because symmetric key management is cumbersome, a hybrid approach is typically used: encrypt the data with a symmetric key, then encrypt that key with the recipient’s public RSA key.
Certificates bind a public key to an identity and are signed by a trusted Certificate Authority (CA). The CA’s private key signs the public key, producing a certificate that can be verified with the CA’s public key.
Apple developer certificate generation
Generate a Certificate Signing Request (CSR) in Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority. This creates a public key publicM and a private key privateM on the Mac.
Upload the CertificateSigningRequest.certSigningRequest to the Apple Developer portal. Apple signs publicM with its private key privateA and returns a developer certificate.
Download the certificate and double‑click to install; the keychain links the certificate with privateM.
Provisioning profile and entitlements
A provisioning profile links a device, an App ID, a bundle ID, capabilities and entitlements to a developer certificate. It is a signed plist file that Xcode embeds as embedded.mobileprovision in the app bundle. The --entitlements option in /usr/bin/codesign adds the app’s entitlement file to the signature.
Entitlements are strings written into the app’s signature that grant specific capabilities (e.g., iCloud, Push). The system checks them before allowing the app to use the corresponding services.
iOS signing verification flow
1. macOS generates a key pair (public M, private M); Apple also generates a key pair (public A, private A). Public A is baked into iOS devices, private A resides on Apple servers. 2. The developer uploads public M (via CSR) to Apple; Apple signs it with private A to create a certificate, which the developer downloads and installs. 3. During development, the developer signs the app with private M and bundles the certificate. 4. At installation, iOS uses public A to verify the certificate, then uses public M to verify the app signature, checks the device UDID, bundle ID, and entitlements, and finally validates the resources listed in _CodeSignature/CodeResources .
Code resources and resource signing
The _CodeSignature folder contains CodeResources.plist, which records hash values (SHA‑1, SHA‑256) for every file in the app bundle except the executable. This ensures that none of the resources have been tampered with.
Step‑by‑step signing and verification
Generate a key pair on macOS.
Upload the CSR; Apple returns a signed certificate and a provisioning profile containing the app ID, entitlements and device UDIDs.
Sign the app with privateM and embed the provisioning profile ( embedded.mobileprovision) into the bundle.
When the device receives the app via Xcode, it first validates the provisioning profile signature with public A, then validates the app signature with public M, checks the device list, bundle ID and entitlements, and finally verifies each resource against CodeResources before creating the sandbox and installing the app.
References
https://developer.apple.com/documentation/xcode/using-the-latest-code-signature-format
https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html
https://pewpewthespells.com/blog/migrating_code_signing.html
http://blog.cnbang.net/tech/3386/
https://developer.apple.com/library/archive/recipes/ProvisioningPortal_Recipes/DownloadingaProvisioningProfile/DownloadingaProvisioningProfile.html
https://developer.apple.com/library/archive/technotes/tn2415/_index.html
https://developer.apple.com/library/archive/qa/qa1814/_index.html#//apple_ref/doc/uid/DTS40014030
https://getupdraft.com/blog/ios-code-signing-development-and-distribution-prov
https://abhimuralidharan.medium.com/what-is-a-provisioning-profile-in-ios-77987a7c54c2
Images illustrating the signing process, certificate generation, provisioning profile structure and verification steps are retained below.
To inspect a local provisioning profile, run security cms -D -i /path/to/iOSTest.mobileprovision.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
