TwitterCopy link

About code signing

Hey, welcome to my new post. 🤗

Today, I will talk about the Code signing stuff, creating a new Certificate, Profile,… in iOS. If you’re in a rush, feel free to skip the first part, My story, to figure out the answer to the question when you’re coming here. Otherwise, stay with my short thought about what pushes me to do this.

My story

Back in the day, the first time I heard about these things, it felt out of sorts because of knowing only a few of its concepts. It was so complicated to me at that time, and now it’s better a bit, enough to stop cursing when dealing with it. 😂
My teammates explained it to me before, theoretical. And I forgot them seemingly immediately, until the time I had to handle it myself, I went around and around pages/blogs to investigated it, and this time taught me a lesson. That’s I need to write it down to look back later and, more importantly, is practice. Even now, when talking about these, I’m still usually open my note to review them. So I thought if the problem I face, again and again, maybe it also happens with others, that’s the reason this post comes in.
I synthesize pieces of knowledge I gained so far into this post. I hope it’s useful for you guys.


What is the iOS code signing?

Before getting started, let’s try google phrase “code signing”. You’ll see the results are a dime of dozen. From my perspective, for an easier life, we should stick with the definition from Apple:

Code signing is a macOS security technology that you use to certify that an app was created by you. Once an app is signed, the system can detect any change to the app—whether the change is introduced accidentally or by malicious code.

So basically, it’s the procedure to make sure the application is integrity that is not involved and edited by someone.

And the basic technique behind it is public-key cryptography on X.509 standard. If you are curious to know more about it, this Wikipedia explains it in much more detail.

Why do we need it?

I suppose you are developing a new iOS application, and now you want to run your code on the real device to try it out first, or maybe because of the simulator’s limitations so you can only test cool features on the real ones, such as:

  • The simulator uses full Mac’s power, so perhaps it’s slow on the real device. Therefore, we should try on the real one to enhance the performance if needed.
  • Some APIs work only with physical devices. And more!

Or you want to distribute your app inside the internal organization, installing on the testers’ device, public on App Store.

And code signing using necessary certificates is a mandatory process to ensure that your app comes from a trustworthy author and hasn’t been modified. In other words, that signs your executable code using issued certificates from Apple.

Big picture

Mention to Code Signing, there are many terminologies relative to, I’m going to show the main flow first, then explain them one by one later.

Firstly, Let’s look at the main flow, which I visualize to easily imagined and memorized for reference later (The first experience with Figma was not bad 😉)

Main flow

  1. Certificate signing request (CSR)

To create a needed certificate, we need to upload the Certificate Signing Request first. You probably can do that from the Keychain Access application:
Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority


Fill in the required information in the dialog, and then select the option Saved to disk. Don’t forget to specify its name or keep the default, CertificateSigningRequest.certSigningRequest.

This step will create a private key in the Keychain and above *.certSigningRequest*, which contains the public key. The system uses these keys to prove that you are the author or have the privilege of sharing this information.
  1. Create Certificate
    To generate a new certificate, you should log in to the Apple developer portal and select the Certificates section.

    There are several options for your choice. For simplifier and focus on the purpose of this post, we should care about the Development and Distribution certificate only, even though the distribution here has kind of variety, App Store, Ad-hoc, In-house, etc. It’s total base on your purpose to distribute the app, and its corresponding available options depend on the kind of program you are attending (regular program or Enterprise one).

    After selecting the desired certificate type, it’s time to upload the CSR which we generated previously. And then Apple issues a new Certificate, download to the local machine. Double click it to add them in the Keychain Access.

    You will see both certificate and corresponding private key in the Keychain Access as here:

    Private key

    We can view its information by right-clicking it and choose the Get info option in the menu. Generally, it contains the subject, issuer, public key info, purpose,…

  2. Create Provisioning profile
    Of course, with Apple’s security things, the certificate is not enough to install an app on devices. We need a Provisioning profile. It holds the information that the OS needs to decide whether to run the app on a particular device. As you can see on the flow picture, the provisioning profile contains:

    • App ID: the unique identifier of your app, which combines team ID and Bundle Identifier.
    • Certificates: the ones we already created in the previous step. You can choose multiple certificates in the Development profile but only one on the Distribution profile.
    • Entitlements: this is the plist file for the sandbox to allow or deny that your app can access the system’s specific resources.
    • UUIDs: the unique identifier of devices we want to install our app. We can get that from the device info in Finder (available on macOS Catalina later) when connecting the device to our mac. For the App Store or In-house distribution, we don’t have to specify these.

    You can create a new one at the Apple developer portal. Just follow these steps: select the type of Profile → for which App ID → select Certificates → select Devices which you want to install on (you won’t see this step if creating the App Store or In-house distribution)→ fill in the name for it. They are pretty straightforward steps.

    After creating a new Provision profile, Xcode automatically downloads it when needed, or you can download it to a local machine and explicit in the Xcode manually.

  3. Set it up in Xcode

In Xcode, going to the Signing & Capabilities tab in the window of selected Target you’re going to build with, don’t forget to choose the correct configuration. You will see the signing information from here. You can let Xcode automatically do it for you by selecting the Automatically manage singing option, choose the team you are in, and Xcode will download the corresponding Profile with your Bundle Identifier. Or the other way is to select the Provision profile you already downloaded in the previous step. In my opinion, I prefer to do it manually.

If everything is okay, just run it on the device. Otherwise, Xcode will show you an error, there are different ways to check depending on the type of error, but mostly we need to check the App ID, the correct Profile, do we have Certificates in the Keychain Access, or is there any difference between entitlements in the profile and current our settings. 😵

  1. Run, run, run

Alright, all prerequisite materials are ready now. When you build and run, Xcode puts the Provisioning Profile onto the iOS device. If iOS proves everything is correct, your target app will be running now. Rock on 🎉 🤘

Common questions

And that’s the whole basic flow you need to know when dealing with code signing stuff. Maybe you’re wondering some things, I list out some questions you may ask and often encountered:

In-house vs. ad-hoc distribution You will hear about the ad-hoc or in-house distribution beside the App Store sometime. Yeah, they're a bit different, instead of widely distributed on the App Store:
  • Ad-hoc: limits the number of registered devices, which means we must collect the device ID and add it into the Profile when creating the Provisioning profile. It’s available for both Individual and Enterprise programs.
  • In-house: we don’t have to collect and specific device ID in the Profile. Instead, end-users have to accept the Profile on their device the first time install your app. It is available for the Enterprise program only.

    For more detailed information, you can refer to the Distribution section in here.

Can I upload an app to the App Store using the Enterprise program? Unfortunately, you can not do that. You have to enroll in the Apple Developer Program and create another app with a different Bundle ID to distribute on the App Store. And that'll cost you another 99$/year.

What if the certificate/profile expired? For this question, I assume you're distributing an app using the Enterprise program because it doesn't affect the app which is on the App Store already.

Basically, we need to generate a new profile/certificate, deploy a new version, and inform users to re-download a new version of the app unless using the MDM to push a new provisioning profile to the devices.

And we do that every one year for Provisioning profile and three years for the certificate with Enterprise program. So you probably should renew and release before they expired for a better user experience.

How to deal with the big team size? Because of the limitation of three distribution profiles for the regular program and 2 for the Enterprise program, every member in a big team can't create their certificate. Fortunately, we can export a certificate from someone in the team with the private key and generate a .p12 format file. Since then we can share that .p12 file and add into Keychain without revoking other's certificate.

To export the certificate we want to share, you probably go to Keychain Access, right-click on the certificate you want to share → select export → change to the name you wish to, and enter a password for that file.

Final thought

That’s pretty much. Of course, there have many things and knowledge relative to each one I mentioned above. This is just the first move before diving into it. So if there has any I need to correct or improve, please sent me feedback. I so appreciate it!

Thanks for spending time with me 🤗

Dang Nguyen - d.f 2021