Get an iOS certificate, p12 and provisioning profile on Windows
To install an iOS app on a phone or submit it to the App Store, you have to sign it, and signing needs a certificate (.p12) and a provisioning profile (.mobileprovision). Apple’s official process generates the CSR in Keychain Access on a Mac. This tutorial does the same on Windows with OpenSSL, from generating the private key to KXBuild signing with the files. You need an account enrolled in the Apple Developer Program, an iPhone and a USB cable. The whole process takes about twenty minutes.
KXBuild doesn’t create certificates in your Apple Developer account for you. It only reads the files you put in the keychain folder. Besides the OpenSSL approach in this tutorial, you can also sign in to your developer account with a tool such as Appuploader and generate them directly. See Certificates and signing.
Which ones you need
| Certificate | When to use it | Matching provisioning profile |
|---|---|---|
| Apple Development | Running and debugging on your own test devices | iOS App Development, must include the device UDIDs |
| Apple Distribution | Uploading to App Store Connect or TestFlight, or building Ad Hoc builds for testers | App Store Connect, or Ad Hoc (must include the device UDIDs) |
When you start developing, you only need an Apple Development certificate and one Development profile. Request Apple Distribution when you’re ready to release. The steps are the same for both types, and the examples below use the development certificate.
Certificates are valid for one year. A team can only have a limited number of distribution certificates, so team members should share one distribution certificate rather than each requesting their own. Development certificates can be one per person.
Generate the private key and CSR with OpenSSL
A CSR (certificate signing request) contains your public key, which you give to Apple to issue the certificate. The matching private key stays on your computer, and you need it later to build the .p12.
Windows doesn’t include OpenSSL, but Git for Windows comes with a copy at C:\Program Files\Git\mingw64\bin\openssl.exe. Run the commands below in PowerShell, saving that path in a variable first. Without Git, you can install OpenSSL with winget or another source and replace & $openssl with openssl.
1$openssl = "C:\Program Files\Git\mingw64\bin\openssl.exe"
2mkdir D:\ios-cert; cd D:\ios-cert
3& $openssl req -new -newkey rsa:2048 -nodes -keyout ios.key -out ios.csr -subj "/emailAddress=you@example.com/CN=Your Name/C=CN"
Replace emailAddress and CN with your email and name. Apple uses the team information on your account when issuing the certificate, so these values only affect the CSR itself. You end up with two files in the folder. ios.key is the private key and ios.csr is the request to upload.
If you run the same command in Git Bash, the
-subjargument starting with/gets rewritten as a path. Prefix the command withMSYS_NO_PATHCONV=1to avoid this. PowerShell doesn’t have this problem.
Keep ios.key safe. If you lose the private key, the certificate can no longer sign, and you have to revoke it and request a new one.
Upload the CSR and download the certificate
- Sign in to developer.apple.com, go to Certificates, Identifiers & Profiles, open the Certificates page and click the plus button.
- Select Apple Development (or Apple Distribution for a distribution certificate) and click Continue.
- Upload ios.csr and click Continue.
- Click Download to get development.cer (a distribution certificate usually downloads as distribution.cer).
The downloaded .cer is in DER format and contains only the certificate, not the private key. It can’t sign on its own.
Build the p12
Convert the .cer to PEM format, then combine it with the private key into a .p12. The second command asks you to enter an export password twice. You’ll write this password into password.properties later.
1& $openssl x509 -in development.cer -inform DER -out development.pem
2& $openssl pkcs12 -export -inkey ios.key -in development.pem -out development.p12
Git for Windows ships OpenSSL 3, which encrypts the .p12 with AES-256 by default. KXBuild reads it as is. If you also import the same file into a Mac keychain or an older signing tool, they may report a wrong password. In that case, export a compatible copy again with -legacy.
1& $openssl pkcs12 -export -legacy -inkey ios.key -in development.pem -out development.p12
To confirm the .p12 contains both the certificate and the private key, run the command below. The output should include both Certificate bag and Shrouded Keybag.
1& $openssl pkcs12 -in development.p12 -info -noout
Register an App ID
On the Identifiers page, click the plus button, choose App IDs > App, and enter a description and Bundle ID.
- Explicit takes the full Bundle ID, such as com.example.myapp, matching PRODUCT_BUNDLE_IDENTIFIER in the project. You must use this type for push notifications, iCloud, Sign in with Apple, App Groups and other capabilities, and check them under Capabilities below.
- Wildcard such as com.example.* lets one profile cover several apps and extensions. It only suits projects in development that don’t use the capabilities above.
If the project has extension targets such as a widget or notification extension, register an App ID for each extension’s Bundle ID (such as com.example.myapp.widget) too. You can see each target’s Bundle ID with kxbuild project info .\MyApp.xcodeproj.
Add test devices
Development and Ad Hoc profiles only allow installing on registered devices, so get your phone’s UDID first.
Connect the iPhone to your computer with a cable, unlock it and tap “Trust This Computer”, then run the command below. The first column is the UDID. The first connection needs the device drivers installed. Follow Set up your device.
1kxdevice device list
With iTunes installed, you can also click the “Serial Number” field on the device summary page to switch it to the UDID. Most third-party device managers also let you copy it from their device info page.
On the Devices page, click the plus button, choose iOS as the Platform, enter a device name and the UDID, and click Continue to save. Each membership year allows up to 100 devices per device type, and deleted devices still count for the rest of the year, so don’t register devices casually.
Create the provisioning profile
- On the Profiles page, click the plus button. Choose iOS App Development for development, App Store Connect for release, and Ad Hoc for builds testers install directly.
- Select the App ID from the previous step.
- Select the certificates to allow. A Development profile can include every team member’s development certificate, so one file works for everyone.
- For Development and Ad Hoc profiles, select the devices to install on. App Store Connect profiles skip this step.
- Give it a recognizable name such as MyApp_Dev, click Generate, then Download to get MyApp_Dev.mobileprovision.
A profile’s certificates, devices and capabilities are fixed when it’s generated. If you add devices, enable new capabilities on the App ID or change certificates later, go back to the Profiles page, edit the profile, save and download it again. Otherwise the build or install fails. For the specific errors and fixes, see iOS code signing and ipa install errors, 16 common fixes.
Put them in the KXBuild keychain folder
There are two keychain folders. The keychain folder in the project root applies to that project only, and the one under KXBUILD_HOME is shared by all projects, which on Windows is %USERPROFILE%\kxbuild\keychain by default. Put the .p12 and .mobileprovision in it, and create password.properties in the same folder with one filename=password line per certificate.
1keychain\
2├─ development.p12
3├─ MyApp_Dev.mobileprovision
4└─ password.properties
1development.p12=the password you set when exporting
The file name must match the .p12 exactly, it’s case-sensitive, and the password has no quotes. Once the files are in place, builds pick the certificate and profile automatically based on the project’s signing settings, with nothing else to configure in KXBuild. For the rules, see Certificates and signing.
Finally, connect the phone, build and install once. If the app opens on the phone, the certificate, profile and device all match.
1kxbuild build .\MyApp.xcodeproj --install
The intermediate files ios.key, ios.csr, .cer and .pem don’t go in the keychain folder.
Expiration, renewal and backup
Before expiration Apple sends a reminder email. When a development certificate expires, development builds signed with it can’t be installed or opened, so rebuild them. When a distribution certificate expires, versions already on the App Store aren’t affected, but Ad Hoc builds stop working and you can’t use it to upload new builds.
Renewal Certificates can’t be extended, only replaced with a new one. Generate and upload a new CSR following this tutorial, or reuse the original ios.key to generate a CSR so you don’t have to manage a new private key. After you get the new certificate, build a new .p12, then on the Profiles page edit every profile that used the old certificate, select the new one, save and download them again, and replace the old files in the keychain folder.
Backup Store ios.key and the finished .p12, along with its password, in a password manager or an encrypted team share. Don’t commit them to your code repository. When you switch computers or set up a build server, just copy the .p12 and password.properties. No need to request new ones.
Lost private key Revoke the certificate on the Certificates page and go through the request process again. Before revoking a distribution certificate, check with your team that nobody is using it to build.