A new approach to code signing

A best practices guide on how to manage certificates and provisioning profiles in your development team.

Wait, what is code signing? Code signing is required on iOS when distributing your app to customers. It assures that your app can be trusted and hasn’t been modified since it was last signed.

See Apple’s docs for more general details on code signing.

The Problem:
Code Signing with Teams

When deploying an app to the App Store, a beta testing service or even installing it on a single device, most development teams have separate code signing identities for every member. This results in dozens of profiles including a lot of duplicates.

Update provisioning profiles across machines

You have to manually renew and download the latest set of provisioning profiles every time you add a new device or a certificate expires. Additionally this requires spending a lot of time when setting up a new machine that will build your app.

Keep Your Keys In-Sync with Git

What if there was a central place where your code signing identity and profiles are kept, so anyone can access them during the build process? This way, your entire team can use the same account and have one code signing identity without any manual work or confusion.

Instead of registering for yet another service, you can use a separate private Git repo to sync your profiles across multiple machines.

Your Keys In-Sync with Git
How to use Git for code signing:

The basic requirement is to have one code signing identity shared across your team. The easiest way to do that is to create a new Apple ID for the team (e.g. ios-dev@company.com) and use that from now on. To get started:

1. First, create a new, private Git repo in which you can store the profiles.

2. Next, create a new private key and certificate for each environment, such as “Distribution” and “Development”. Then store these private keys and certificates in your Git repo.

3. Then, create a new provisioning profiles for the various targets, such as “Development”, “App Store” and “Ad hoc” with the matching certificates and store these in your Git repo.

4. Before committing the files to Git, it is recommended to encrypt those files (e.g. using openssl).

5. Now, each of your machines can access the Git repo and install the latest certificate and provisioning profiles: - The certificates and private keys should be imported into your Keychain, either using Finder or using the 'security import' command - The provisioning profiles should be copied over to '~/Library/MobileDevice/Provisioning\ Profiles/'

6. Your Xcode project must be configured to choose the provisioning profiles automatically or define it statically. The ideal solution is to pass the UUID of the provisioning profile, via an environment variable, for each of your bundle identifiers.

In the future, when you add a new device to your Ad Hoc or Development provisioning profile, you can update the profile in your Git repo.


Things to consider:
Is this secure?
Expand for more

Both your keys and provisioning profiles are encrypted using OpenSSL using a passphrase.

Storing your private keys in a Git repo may sound off-putting at first. We did an in-depth analysis of potential security issues and came to the following conclusion:

What could happen if someone stole a private key?

If attackers would have your certificate and provisioning profile, they could codesign an application with the same bundle identifier.

What's the worst that could happen for each of the profile types?

App Store Profiles

An App Store profile can't be used for anything as long as it's not re-signed by Apple. The only way to get an app resigned is to submit an app for review (which takes around 7 days). Attackers could only submit an app for review, if they also got access to your iTunes Connect credentials (which are not stored in Git, but in your local keychain). Additionally you get an email notification every time a build gets uploaded to cancel the submission even before your app gets into the review stage.

Development and Ad Hoc Profiles

In general those profiles are harmless as they can only be used to install a signed application on a small subset of devices. To add new devices, the attacker would also need your Apple Developer Portal credentials (which are not stored in Git, but in your local keychain).

Enterprise Profiles

Attackers could use an In-House profile to distribute signed application to a potentially unlimited number of devices. All this would run under your company name and it could eventually lead to Apple revoking your In-House account. However it is very easy to revoke a certificate to remotely break the app on all devices.

Because of the potentially dangerous nature of In-House profiles please use match with enterprise profiles with caution, ensure your git repository is private and use a secure password.

To sum up

Making things simple with match

To make it easy for you to implement this new approach to code signing, fastlane now provides a new tool called match.

match takes care of all the heavy lifting for you, including:

Generates your code signing identity

Generates your code signing identity and provisioning profiles if necessary.

Stores everything in a separate Git repository

Stores all certificates and provisioning profiles in a separate Git repository.

Automatically installs the certificates

Automatically installs the certificates and provisioning profiles from the repository.

To get started, create a new private Git repo and run:

fastlane match init
match init

To generate and store new certificates and provisioning profiles run:

fastlane match appstore


fastlane match development
match appstore

On a new machine, just run fastlane match appstore to install the existing certificates.

If you never really cared about code signing and have a messy Apple Developer account with a lot of invalid, expired or Xcode managed profiles/certificates, you can use the fastlane match nuke command to completely clear your developer portal.

This command will revoke all certificates and provisioning profiles for a specific environment.

Simply run:

fastlane match nuke development
fastlane match nuke distribution
match nuke

Reduce the time it takes to build & deploy your app

Learn more about how fastlane unifies and automates your app's release process.