Once you have done any work on an iOS app, you have run into the Provisioning Profile. Odds are you went through Apple’s “Development Provisioning Assistant,” installed your profile in the correct place, got your certificate and key installed into the Keychain using Keychain Access.app, and went on your merry way. But, sometime later, you more than likely ran into one of the following problems:
Code Sign error:
- The executable was signed with invalid entitlements.
- Valid signing identity not found.
- No unexpired provisioning profiles found that contain any of the keychain’s signing certificates
You probably Googled around, found something like your problem on Stack Overflow that might have fixed your issue, and moved on. More often than not, I see the nuclear option posted as a solution: “Delete all your profiles and start over.” Often this will work, but the goal of this series of posts is to arm you with the knowledge you need to fix your specific problem without having to go nuclear.
Let’s get started.
Every Provisioning Profile is really a PKCS#7 signed plist. PKCS stands for Public Key Cryptography Standards. PKCS#7 is the version that supports the Cryptographic Message Syntax. Apple uses these signed plists so the OS can verify that the application being installed is from the right developer and that the content inside the plist has not been modified. That last part is important, and you will find out why later.
Open a Provisioning Profile from the Terminal.app using vi, and you will see something very much like this:
0<82>^^è^F *<86>H<86>÷^M^A^G^B <82>^^Ù0<82>^^Õ^B^A^A1^K0 ^F^E+^N^C^B^Z^E^@0<82>^N®^F *<86>H<86>÷^M^A^G^A <82>^N<9f>^D<82>^N<9b><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>
All that junk at the top is the header of the PKCS#7 signature. If you jump to the bottom you will see a whole bunch more. That is where the real meat of the signature is:
</dict> </plist> <82>^M²0<82>^Cù0<82>^Bá ^C^B^A^B^B^A^_0^M^F *<86>H<86>÷^M^A^A^E^E^@0y1^K0 ^F^CU^D^F^S^BUS1^S0^Q^F^CU^D ^S Apple Inc.1&0$^F^CU^D^K^S^]Apple Certification Authority1-0+^F^CU^D^C^S$Apple iPhone Certification Authority0^^^W^M080521020415Z^W^M200521020415Z0Y1^K0 ^F^CU^D^F^S^BUS1^S0^Q^F^CU^D ^S Apple Inc.1503^F^CU^D^C^S,Apple iPhone OS Provisioning Profile Signing0<82>^A"0^M^F *<86>H<86>÷^M^A^A^A^E^@^C<82>^A^O^@0<82>^A
Looking closely through that footer, you should notice something familiar. Strings like Apple Inc., Apple Certification Authority, and Apple iPhone OS Provisioning Profile Signing are clues to who digitally signed this file. Provisioning Profiles are created at the iOS Provisioning Portal. After you have selected the App ID, the appropriate number of device UDIDs and the appropriate Entitlements, Apple digitally signs all this information into a Provisioning Profile that iOS can verify really came from Apple.
Since this file is digitally signed, you should be asking, “how do I verify the signature?” With Terminal.app, you can use the openssl program to do the verification. Openssl will not only verify the signature but will also output the signed message, in our case a plist, in plain text:
openssl smime -in /path/to/your.mobileprovision -inform der -verify
Now, let’s say you want to edit the Provisioning Profile by hand. Maybe you would like to add the UDID of some shiny new Apple device without going through the Provisioning Portal. The verification would fail like this:
openssl smime -in Key_Grinder_Beta_Dev.mobileprovision -inform der -verify Error reading S/MIME message 10163:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:1315: 10163:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:657:Field=signer_info, Type=PKCS7_SIGNED 10163:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:747: 10163:error:0D08403A:asn1 encoding routines:ASN1_TEMPLATE_EX_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:577:Field=d.sign, Type=PKCS7
Not the best error I have ever seen, but it does the trick. Apple limits each developer account to 100 devices to prevent you from adding more UDIDs yourself.
This post has introduced you to the basics of a Provisioning Profile. I hope you have been intrigued enough to come back for the next part in the series where I will dig into the contents of the plist and what that information means to you, your apps and Xcode.