Article

Generate iOS Signing Certificates and Provisioning Profiles

21 min read
iOS Provisioning Profiles, Certificates, and Code Signing

iOS signing in Kobiton environments involves three related tasks: understanding how iOS code signing works, generating signing certificates and provisioning profiles, and importing those files into a device host.

This guide focuses on generating signing certificates and provisioning profiles. For related tasks, see the guides listed in Related guides at the end of this document.

Overview

This guide explains how to generate the signing certificate and provisioning profile required for iOS app signing.

In iOS workflows, two files are typically required:

● a signing certificate (.p12), which is used to sign the app during the build process

● a provisioning profile (.mobileprovision), which authorizes the signed app to run on specific devices

These files are generated using the Apple Developer portal and Keychain Access on macOS.

This guide covers:

● creating a certificate signing request (CSR)

● generating an Apple Development certificate

● exporting the certificate as a .p12 file

● creating a development provisioning profile

● editing an existing provisioning profile when devices or certificates change

Prerequisites

Before generating certificates and provisioning profiles, ensure the following requirements are met:

● You are enrolled in the Apple Developer Program or Apple Developer Enterprise Program

● Your developer account has an available Apple Development certificate slot

● You have access to a macOS machine with Keychain Access

● You have permission to access Certificates, Identifiers & Profiles in the Apple Developer portal

● You have the UDIDs of any devices that will be authorized for development builds

Also confirm the following about the Apple Developer account you will use:

  • Role. Creating and editing provisioning profiles and registering devices requires the Account Holder or Admin role. A team member with the Developer role can create their own Apple Development certificate but cannot create profiles, so either request Admin for the person running this guide or have an Admin perform the Profiles and Devices steps.
  • Sign-in. Apple requires two-factor authentication on the Apple Account used for the developer portal. Have the trusted device or phone number available before you start.
  • Certificate headroom. Apple caps the number of active certificates of each type per account and per team member. If the + button on the Certificates page reports that the maximum has been reached, revoke a certificate that is no longer used (after confirming no profile still depends on it) rather than creating a second account.
  • Device headroom. Up to 100 devices per product family can be registered per membership year. Check the Devices page count before bulk-registering a lab.
  • Program type. The Apple Developer Program produces the development profiles this guide describes. The Apple Developer Enterprise Program additionally produces In-House profiles that do not list devices; the development-certificate steps are the same on both.

If managing multiple host machines, it is recommended to generate certificates and provisioning profiles on a limited number of machines for easier management.

Choose the certificate and profile type before you start

The steps in this guide produce an Apple Development certificate and an iOS App Development provisioning profile. That pairing is correct for most device-lab and automation workflows: a development profile can list the UDIDs of hosted devices, and the resulting .p12 can sign apps for installation and debugging on them. It is not the only valid pairing. Match the pairing to how the signed app will be used.

ScenarioCertificate to createProfile typeDevice UDIDs in profileNotes
Install and automate test builds on hosted devices (default for this guide)Apple DevelopmentiOS App Development (under Development)YesSupports the get-task-allow debugging entitlement that automation tooling relies on. Use this unless you have a reason not to.
Install a release-candidate build signed for distribution on a fixed set of devicesApple DistributionAd Hoc (under Distribution)YesNo debugging entitlement. Same portal steps as below, with the two substitutions listed after this table.
Internal distribution on an Apple Developer Enterprise Program accountApple Distribution (In-House)In-House (under Distribution)NoEnterprise-signed apps do not list devices. Confirm whether your device lab re-signs enterprise apps or installs them as-is before choosing this route.
Submit to TestFlight or the App StoreApple DistributionApp Store ConnectNoNot applicable to device-lab signing; included so the reader knows which options to skip in the portal.

To produce an Ad Hoc profile instead of a development profile, follow the same steps with two changes:

  • In Certificates, choose Apple Distribution instead of Apple Development when creating the certificate from the CSR.
  • In Profiles, choose Ad Hoc under Distribution instead of iOS App Development, and select the Apple Distribution certificate when prompted.

A development certificate cannot be included in an Ad Hoc profile, and a distribution certificate cannot be included in a development profile. If you need both workflows, generate both certificates and keep them in the same login keychain; one CSR can be reused for both.

Generate an Apple Development certificate

Create a Certificate Signing Request (CSR)

A certificate signing request (CSR) is used to generate the Apple-issued signing certificate.

  1. Open Keychain Access on the macOS machine.
  2. From the menu bar, select
    Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority.
  3. Enter the following information:

○     Email Address

○     Common Name

  1. Leave CA Email Address empty.
  2. Select Saved to disk.
  3. Save the generated .certSigningRequest file.

When the CSR is created, macOS automatically generates a public/private key pair in the Login keychain.

This key pair must remain in the keychain. If it is removed, the resulting certificate cannot be used.

Create the development certificate in Apple Developer

  1. Log in to the Apple Developer portal.
  2. Navigate to Certificates, Identifiers & Profiles.
  3. Select Certificates.
  4. Select the + button to create a new certificate.
  5. Choose Apple Development, then select Continue.
  6. Upload the .certSigningRequest file generated earlier.
  7. Select Continue.
  8. Download the generated .cer certificate file.

This certificate must be downloaded and installed on the same machine where the CSR was created.

Export the certificate as a .p12 file

The .p12 file contains both the certificate and its associated private key.

  1. Open Keychain Access.
  2. Select the Login keychain.
  3. Import the downloaded .cer certificate.
  4. Expand the certificate to confirm that a private key is associated with it.
  5. Select both the certificate and its private key.
  6. Right-click and select Export 2 items.
  7. Choose Personal Information Exchange (.p12) as the file format.
  8. Save the file.

You will be prompted to set a password to protect the certificate.

Treat the .p12 and its password as a production credential: anyone holding both can sign apps as your team.

  • Store the .p12 in a secrets manager or the team password manager, with the password as a separate entry. Do not commit it to a repository, even a private one, and do not send it over chat or email.
  • Keep a record of which hosts have received it, so that when the certificate is renewed every copy is replaced.
  • Limit who can export from the originating keychain. The private key in the login keychain is the master copy; if the machine is reimaged without an exported .p12, the certificate must be regenerated.

To install the .p12 on a host, either double-click it and enter the password in Keychain Access, or run the following in Terminal so that codesign can use the key without prompting during automated signing:

security import <file>.p12 -k ~/Library/Keychains/login.keychain-db -P “<password>” -T /usr/bin/codesign -T /usr/bin/security

The -T flags add codesign and security to the key’s access list. Without them, the first signing operation on the host opens a keychain prompt that an unattended process cannot answer. Copy the matching .mobileprovision file to the host as well, or install it by double-clicking; Xcode and most tooling read profiles from ~/Library/MobileDevice/Provisioning Profiles. From Xcode 16 onwards, Xcode reads them from ~/Library/Developer/Xcode/UserData/Provisioning Profiles instead; confirm which path your host’s tooling expects.

Store the .p12 file securely and transfer it to any machines that require signing access.

If the imported certificate does not display a private key, confirm that:

● The certificate was imported on the same machine where the CSR was created

● the original key pair in the Login keychain has not been deleted

Alternative: create the CSR and .p12 without Keychain Access

Keychain Access is a convenience, not a requirement. The same files can be produced with OpenSSL on macOS or Linux, which is useful when certificates are generated by a script or on a non-Mac machine. The Apple Developer portal steps are unchanged.

1. Generate a private key: openssl genrsa -out signing.key 2048

2. Generate the CSR from it: openssl req -new -key signing.key -out signing.certSigningRequest -subj “/emailAddress=<email>/CN=<name>/C=<country code>”

3. Upload signing.certSigningRequest in the portal exactly as in Create the development certificate in Apple Developer, and download the resulting .cer file.

4. Convert the certificate to PEM: openssl x509 -inform DER -in development.cer -out development.pem

5. Bundle the certificate and key into a .p12: openssl pkcs12 -export -inkey signing.key -in development.pem -out signing.p12. You will be prompted for the export password. If the file will be imported into Keychain Access on an older macOS and the import fails, repeat with -legacy added after pkcs12.

Guard signing.key with the same care as the .p12; it is the private half of the certificate. Browser-based generators such as Capawesome’s do the same thing with the Web Crypto API and are fine for an individual developer, but for a shared lab certificate prefer a process you control and can repeat.

Xcode’s automatic signing is a third option and the right one for day-to-day development builds, but it is not suited to device-lab signing: Xcode-managed profiles are created per project and per Mac, are regenerated without notice, and are not meant to be copied to other hosts. Use the manual portal flow in this guide whenever the .mobileprovision file needs to travel.

Generate a Development Provisioning Profile

Provisioning profiles determine which devices and certificates are authorized to run a signed app.

Create an App ID (if required)

If an appropriate App ID does not already exist:

  1. Log in to the Apple Developer portal.
  2. Navigate to Identifiers.
  3. Select the + button.
  4. Choose App IDs, then select Continue.
  5. Select App as the identifier type.
  6. Enter:
  • an App ID description
  • a Bundle ID

Wildcard bundle IDs can be used when signing multiple apps that share the same domain.

Which bundle ID pattern to use depends on how the profile will be consumed.

  • If you use the Kobiton re-signing service, create a wildcard App ID with the bundle ID com.*. The Kobiton iOS agent app has a bundle ID beginning with com., and the same profile then covers any app under test whose bundle ID starts with com. (for example com.company.appname).
  • If your apps use other prefixes, create one additional wildcard App ID per prefix (org.*, net.*, io.* and so on). Because a provisioning profile holds exactly one App ID, each prefix needs its own profile, signed with the same certificate.
  • If you do not use the re-signing service and sign a single app yourself, an explicit App ID matching the app’s exact bundle ID is simpler to audit and is required for most capabilities (see below).
  • Wildcard App IDs cannot enable capabilities that require an explicit identifier, including Push Notifications, App Groups, Associated Domains, Sign in with Apple, iCloud and most Apple Pay and HealthKit features. If the app under test depends on one of these, create an explicit App ID for it, enable the capability on that App ID, and generate a separate provisioning profile for it.
Apps to signApp IDs to createProfiles to generate
Kobiton agent plus any com.* appscom.* (wildcard)1 development profile
Kobiton agent plus apps under org.* and io.*com.*, org.*, io.* (three wildcards)3 development profiles, one per App ID
One app that uses push notifications or App GroupsExplicit App ID (e.g. com.company.appname) with the capability enabled1 profile for that App ID, in addition to any wildcard profile

The capabilities enabled on an App ID at the moment a profile is generated are the entitlements that profile grants. Enabling or removing a capability on an App ID later marks every existing profile for that App ID as invalid in the portal; edit and regenerate each one, then redistribute the new .mobileprovision files.

Only one App ID can be associated with a provisioning profile.

Register Device UDIDs

Development provisioning profiles require the UDIDs of devices that will run the signed app.

Find a device’s UDID

Any of the following returns the identifier the portal expects. On iPhone XS and later the UDID is 25 characters with a hyphen after the eighth (for example 00008030-001A2B3C4D5E6F7G); on older devices it is 40 hexadecimal characters. The portal accepts both formats.

  • Finder (macOS 10.15 or later): connect the device, select it in the Finder sidebar, then click the text directly under the device name until it shows the UDID. Right-click it to copy.
  • Xcode: open Window → Devices and Simulators, select the device, and copy the Identifier field.
  • Command line (Xcode 12 or later): run xcrun xctrace list devices. Each connected device is listed with its UDID in parentheses. On a host with libimobiledevice installed, idevice_id -l prints the UDIDs of all connected devices, one per line, which is convenient for scripting bulk files.
  1. Navigate to Devices in the Apple Developer portal.
  2. Select the + button.
  3. Enter the device name and UDID.
  4. Select Register.

Register many devices at once

1. Create a plain-text file (.txt or .deviceids) with a header row and one tab-separated row per device, in the form Device ID <tab> Device Name. The portal rejects comma-separated files.

2. Navigate to Devices in the Apple Developer portal, select the + button, then choose Register Multiple Devices.

3. Upload the file, select Continue, review the list, then select Register.

Three limits apply to registered devices:

  • Apple allows up to 100 registered devices per product family (iPhone, iPad, Apple Watch, Apple TV, Mac and so on) per membership year. Removing a device does not free its slot until the membership renews, so disable retired devices rather than registering replacements casually.
  • Devices registered after a profile was generated are not in that profile. Edit the profile, add the devices, save, download and redistribute it (see Edit an existing provisioning profile).
  • Enterprise Program accounts do not need device registration for In-House profiles, but still need it for development profiles.

Multiple devices can also be registered using Apple’s bulk upload method.

Create the Development Provisioning Profile

  1. Navigate to Profiles in the Apple Developer portal.
  2. Select the + button to create a new profile.
  3. Choose iOS App Development under Development.
  4. Select the appropriate App ID.
  5. Select the Apple Development certificate created earlier.
  6. Select the registered device UDIDs.
  7. Enter a provisioning profile name.
  8. Select Generate.

Download the generated .mobileprovision file.

This file can now be used on host machines to authorize apps signed with the corresponding certificate.

Verify the certificate and profile before you distribute them

A .p12 without its private key, or a profile that omits the device you need, fails only when an app is installed on a host, usually with an error that does not name the cause. Run these checks on the macOS machine where the files were generated before copying them anywhere.

1. Confirm the signing identity is usable. In Terminal, run security find-identity -v -p codesigning. The output must list the new certificate with a 40-character hash and a name of the form Apple Development: <name> (<team ID>). If the certificate is absent from the -v (valid) list, the private key is missing or the Apple WWDR intermediate certificate is not installed.

2. Read the profile’s contents. Run security cms -D -i <profile>.mobileprovision to print the profile as a plist. Check that Name matches what you entered, TeamIdentifier is your team, Entitlements → application-identifier ends in the App ID you chose (for example TEAMID.com.*), ProvisionedDevices lists every UDID you expect, and ExpirationDate is roughly a year out.

3. Confirm the profile contains the certificate you exported. The DeveloperCertificates array in the same output holds the certificate as base64 DER. On macOS 12 or later, run security cms -D -i <profile>.mobileprovision | plutil -extract DeveloperCertificates.0 raw – | base64 -d | openssl x509 -inform DER -noout -fingerprint -sha1 and compare the fingerprint with the hash from step 1. They must match.

4. Confirm the .p12 carries the private key. Run openssl pkcs12 -in <file>.p12 -nodes -info 2>/dev/null | grep -c “PRIVATE KEY”. The result must be 1. On OpenSSL 3.x, add -legacy before -in; Keychain Access exports .p12 files with older encryption that OpenSSL 3 only reads in legacy mode.

If any check fails, use this table to find the fix without regenerating everything.

SymptomLikely causeFix
Certificate not listed by security find-identity -vPrivate key not in the login keychain, or the CSR was created on a different machineGenerate a new CSR on this machine and create a new certificate from it; revoke the orphaned one in the portal
Certificate listed but marked as not trusted in Keychain AccessApple Worldwide Developer Relations intermediate certificate missingDownload the current WWDR intermediate from Apple’s certificate authority page and import it into the login keychain
ProvisionedDevices is missing a deviceDevice registered after the profile was generated, or not selected when the profile was createdEdit the profile, select the device, save, download and redistribute
application-identifier does not match the appWrong App ID selected, or app bundle ID does not match the wildcard prefixGenerate a profile for the correct App ID (see Create an App ID)
Fingerprints in steps 1 and 3 differProfile was generated against a different certificateEdit the profile, select the correct certificate, save and regenerate
grep returns 0 for PRIVATE KEYOnly the certificate was exported, not the keyIn Keychain Access, expand the certificate, select both items, and export again as .p12

Edit an existing provisioning profile

Provisioning profiles can be edited to add new devices or certificates.

  1. Navigate to Profiles in the Apple Developer portal.
  2. Select the provisioning profile to modify.
  3. Select Edit.
  4. Update any of the following:
  • profile name
  • associated certificates
  • authorized device UDIDs
  • App ID
  1. Select Save.
  2. Download the updated provisioning profile.

After editing a profile, the updated .mobileprovision file must be redistributed to any machines that use it.

Editing a provisioning profile resets its expiration date.

Frequently asked questions

Do I need a separate certificate for each Mac mini host?

No. Generate one Apple Development certificate on one machine, export it as a .p12, and import the same .p12 on every host that needs to sign. One shared certificate means one renewal per year and one set of profiles to maintain, which is why this guide recommends generating on one or two machines only.

Can one provisioning profile cover several apps?

Yes, if the profile’s App ID is a wildcard such as com.* and every app’s bundle ID starts with that prefix. A profile holds exactly one App ID, so apps under different prefixes need separate profiles. Apps that use capabilities such as push notifications or App Groups need an explicit App ID and their own profile.

Why doesn’t my exported .p12 contain a private key?

The private key is created in the login keychain of the machine where the CSR was made. If the .cer was imported on a different machine, or the key was deleted, the certificate has no key to pair with. Generate a new CSR on the machine you will export from, create a new certificate from it, and revoke the orphaned one.

I registered a new device. Why can’t it install the app?

Registering a device does not add it to existing profiles. Edit the provisioning profile, select the new device, save, download the regenerated .mobileprovision, and copy it to every host that uses it.

How long are the certificate and profile valid?

An Apple Development certificate is valid for one year from issue. A development provisioning profile is valid for one year from generation, or until the earliest certificate it contains expires. Editing and saving a profile regenerates it with a new one-year expiry.

What’s the difference between a development profile and an ad hoc profile?

Both list specific device UDIDs. A development profile pairs with an Apple Development certificate and permits debugging, which automation tooling relies on; an ad hoc profile pairs with an Apple Distribution certificate and produces a distribution-signed build with no debugging entitlement. Use development for test and automation builds on hosted devices, and ad hoc only when you need to install a build signed exactly as it will ship.

Can I generate these files without a Mac?

The CSR and the .p12 can be produced with OpenSSL on any platform or with a browser-based generator, and the Apple Developer portal runs in any browser. Signing itself and the Kobiton device hosts still run on macOS, so a Mac is needed somewhere in the workflow.

Certificate and profile expiry: what to renew and when

Every file generated in this guide expires. Record the dates when you generate them; the portal shows them under Certificates and Profiles, and the ExpirationDate key inside the .mobileprovision file shows the profile’s own date.

ItemLifetimeWhat happens when it expires or is revokedHow to renew
Apple Development certificateOne year from issueApps already installed keep running. New signing with the certificate fails, and every provisioning profile that includes it becomes invalid.Create a new CSR and certificate (steps above), export a new .p12, edit each affected profile to add the new certificate, then redistribute both files to every host.
Development provisioning profileOne year from generation, or earlier if an included certificate expires firstApps signed with the profile stop launching on the device once the embedded profile expires, and new installs fail.Edit the profile and save it to regenerate with a fresh expiry; download and redistribute.
Registered deviceNo expiry, but counted against the membership yearNothing; the per-family device allowance resets when the membership renews.Disable devices you no longer use rather than deleting them, since deletion does not free a slot until renewal.
Apple Developer Program membershipOne yearAll certificates and profiles under the account become invalid when the membership lapses.Renew the membership before the date; nothing else needs regenerating if renewal is on time.

A few practices avoid the outage:

  • Renew the certificate before it expires, not after. Generate the replacement while the old one is still valid, add it to every profile alongside the old one, redistribute, and only then revoke the old certificate. Revoking a certificate immediately invalidates every profile that contains it.
  • Put the expiry dates somewhere the whole team sees them, with a reminder at least a month out. Renewing on a quiet day takes under an hour; discovering an expiry when a host refuses to install an app takes the rest of the day.
  • Keep the number of certificates small. One development certificate shared across hosts means one renewal per year. One certificate per host or per engineer means a renewal somewhere every few weeks.
  • After any renewal, re-run the verification checks above on one host before rolling the files out to the rest.fv