What are code signing identities?
What are "code signing identities" in XCode?
Are they the certificates?
Are they the private keys?
Are they the app ids?
Are they the provisioning profiles?
If I go to the target build settings, it asks for the code signing identity, so I need to figure this out.
I thought we signed code using our private key. None of my private key names show up, however. It shows a list of certificates (I think, though I am not even sure.)
You've definitely hit on a topic that gets very deep very quickly and is a common source of headaches when trying to make device builds of iOS applications. First, let me put a little structure around each of the terms involved in the Code Sign process (both for you and anyone stumbling across this question later) and then we can turn to your main question:
CodeSign Terminology
The Code Sign phase of an iOS Device build is the process by which we cryptographically sign and secure a specific arrangement of data in an application including the application executable binary itself, any embedded media assets (like button textures, custom artwork, fonts, etc.), and a set of metadata about our application and represents a unique 'thumbprint' of our application's data. This thumbprint is what is used by Apple and iOS to help ensure that our applications are not tampered with when being delivered to user's devices or when being run on user's iOS devices. To make this possible Developers are required to register with Apple, setup an App Identifier, request Development and Distribution Certificates, Register a set of Test Devices, and finally request a Provisioning Profile for their development efforts. The role each of these elements is as follows:
- App Identifier (or AppID) - A reverse DNS-style string that uniquely identifies exactly one iOS application on the AppStore.
- Development and Distribution Certificates - These are digital documents cryptographically signed by Apple certifying the identity of the individual to which the documents were issued. For those familiar with Public Key Infrastructure, the Certificate itself contains a public key that can be used to verify the integrity of signatures later in the process.
- Test Devices - The only approved standard distribution channels for iOS software is via the AppStore. By registering a test device, developers may circumvent the AppStore and install software directly to devices for development and testing purposes. The total number of test devices allowed in a given membership year is 100 test devices.
- Provisioning Profile - A document containing three main components: 1) Exactly one App ID, 2) One or more iOS Developer Certificates, and 3) Zero or more registered test devices on which the named iOS app may be directly installed. The contents of this document are cryptographically signed by Apple to ensure its contents can not be tampered with.
It is the presence of this file and the thumbprint checks that determines if a developer-generated app can be installed to device as it contains the notion of the 'Who' (Certificates), the 'What' (AppID), and the 'Where' (which devices).
Great, I got it...Now what about this Code Sign Identity thing?
In the context of an individual build target's build settings, the term Code Sign Identity refers to the Common Name of those certificates that are installed in the Keychain of the Developer's machine. In the Xcode build setting it appears as a list of options from which developers must select an Identity to use for CodeSign -- there's a lot of information encoded in each section of this menu:
Looking first at the black text - From the image above 'iPhone Developer: Bryan Musial (XXXXXXXXXX)' - This is really the primary item Xcode uses to find the public and private keys used to Code Sign. When selecting this item, you are instructing Xcode to reach into your Keychain and try to find a certificate whose 'Common Name' field matches that string and then grab that certificate (which contains the public key) and the associated private key for use in the Code Sign operation.
Just to be thorough if you open up Keychain Access and double click any of the 'iPhone Development: ...' or 'iPhone Distribution: ...' certificates shows all of the information encoded into the certificates Apple issues to its developers. If I were to select the entry in the first image, Xcode would reach into my Keychain and pull back this certificate (NOTE: Unique identifying details have been X'd or changed):
As you can see, the black text from the Xcode selection exactly matches the Common Name field in my certificate, so Xcode would pull back this certificate and its linked private key for use in Codes Signing my app.
Looking back at the Xcode setting again, we also notice that there is more text in that menu selection as well -- the lighter gray text identifies the Provisioning Profile that will be built into the application. In the case of my example setting, Xcode will go and get the Provisioning Profile "MyiOSApp Testing" which has its AppID set to 'com.myiosapp.*'. Xcode is very greedy with stashing Provisioning Profiles, and fortunately Organizer gives you a great place to look over the Provisioning Profiles that are installed and get a sense about the basic data they contain. Again for the Xcode Code Sign Identity in the first image, the related Provisioning Profile in my Organizer would look like this:
The 'Name' column and the tail end of the App Identifier column match the light gray text from my Xcode setting so this is the Provisioning Profile that would get selected for use during Code Sign. It is also important to note the 'Status' column at the end of the row. In this case, it is green and indicates 'Valid Profile'. This means that my Keychain has both the Public and Private keys for at least one of the certificates encoded in that Provisioning Profile. If this status is anything other than green then there is a problem with your current setup of Public/Private Keys and/or the Provisioning Profile -- Code Signing can not work unless the Provisioning Profile you are trying to use has its status set to Green. Other possible status options include:
- Valid signing identity not found: You do not have both the Public and Private key for at least one of the Certificates encoded in this Provisioning Profile. Delete the profile from Organizer, then return to the Certificates, Identifiers & Profiles tool on developer.apple.com/ios and ensure you have your Development Certificate included in the Provisioning profile. Verify your certificate in Keychain Access is not expired or revoked and has a private key linked to the public key certificate.
- Profile has expired: The expiry date for the provisioning profile has lapsed. Delete this Provisioning Profile from Organizer, then revisit the Certificates, Identifiers & Profiles tool on developer.apple.com/ios and reissue this Provisioning Profile (if it is actually still needed)
Other items that can trip you up
In addition to all of the nuances about making sure you have both Public and Private keys installed, and that the Provisioning Profiles are set just right, there are a few other things that can trip developers up. First, Xcode collects Provisioning Profiles and hangs on to them until you tell it to delete them. In theory, this isn't a super huge deal except in scenarios where you make changes to a Provisioning Profile, download and install a newer version. Many times Xcode will grab the right profile, but sometimes it doesn't get it right and you'll spend hours looking over the Certificates, Identifiers & Profiles tool as well as your keychain to try and get an idea about what is going on.
Suggestion 1: When installing a newer version of a Provisioning Profile, delete older ones so that Xcode isn't put in a position where it may have to make a decision.
A similar thing can happen if you reissue a Development or Distribution Certificate -- Most times Xcode will trigger a warning during the build about an ambiguous certificate.
Suggestion 2: Pay attention to ambiguity warnings during the build. It implies that you have an old certificate floating around that meets the build criteria and could be inadvertently used potentially causing a build problem.
Suggestion 3: Anytime you are in Keychain dealing with your certificates, look for 'iPhone Developer: ...' or 'iPhone Distribution: ...' certificates that have a red 'X' on them. This is an indicator that the certificate has expired or has been revoked. Either way, this Public Key (and potentially linked Private key) is of no further use to you for build purposes and can be deleted.
Finally, the Code Sign Identity setting also has an option that lists as 'Automatic Profile Selector'. In many cases you will want to use this option as it will do its best to automatically look up your AppID from your build target's settings, look for a Provisioning Profile that matches that AppId and contains certificates that you have both a public and private key for. In some custom build circumstances it may not be possible to use this option and you'll have to use one of the fixed, specific options, like my demonstration setting in the first image. Be advised if you go with a fixed option -- any time you update the Provisioning Profile, you will need to also update the Code Signing Identity build setting to match the newer version.
Key Takeaways
- Make sure you keep both your Keychain and Xcode Provisioning Profile lists clean and deduplicated.
- After installing a Certificate and Provisioning Profile, make sure the Organizer reports that provisioning profile's status as Green ('Valid profile'). Any other status indicates a problem exists between your keychain and provisioning profile that needs to be addressed before you even consider running a build.
- Try and use the 'Automatic Profile Selector'. Your teammates and any automated build systems will be happier with you if they too don't have to think about Code Sign Identity settings.
- If you can't use the Automatic Profile Selector, make sure you always keep that setting up-to-date as newer iterations of your provisioning profile are made.
Good luck with your build configuration, and please let me know if you have any other follow up questions!