# Zo werkt iOS code signing: certificates, provisioning profiles en private keys

> iOS code signing uitgelegd: hoe signing certificates van Apple, provisioning profiles en private keys samenhangen, de soorten certificates en profiles, en hoe je signt in CI.

Door Koen Van Looveren, impaktfull · Gepubliceerd 2025-06-12 · Bijgewerkt 2026-11-07

Bron: https://www.impaktfull.com/nl/blog/how-ios-code-signing-works-certificates-provisioning-profiles-private-keys

Wanneer je begint te ontwikkelen voor iOS, bots je al snel op het **code signing**-systeem van Apple. Signing certificates, provisioning profiles, entitlements, private keys: het kan aanvoelen als een verwarrende black box.

## TL;DR: samenvatting

- Je maakt een **private key** aan op je Mac.
- Apple geeft je een **certificate** dat je identiteit aan je key koppelt.
- Een **provisioning profile** bepaalt waar en hoe je app kan draaien.
- iOS controleert alles voor de app geïnstalleerd en uitgevoerd mag worden.

## Waarom vereist iOS code signing?

Apple gebruikt code signing om:

- te verifiëren dat een app van een gekende, betrouwbare developer komt.
- ervoor te zorgen dat er na het signen niet met de app geknoeid is.
- te bepalen welke apps op iOS-toestellen geïnstalleerd kunnen worden (voor de veiligheid & controle over het App Store-ecosysteem).
- bepaalde features voor te behouden aan geautoriseerde developers (zoals Push Notifications, HealthKit, enz.).

Geen gesignde app → geen installatie.

## De belangrijkste spelers

Dit zijn de belangrijkste onderdelen die meespelen bij het signen van een iOS-app:

| Onderdeel | Beschrijving |
| --- | --- |
| Apple Developer Account | Je geregistreerde identiteit als developer bij Apple. |
| Certificate Signing Request (CSR) | Een bestand dat je genereert om een certificate aan te vragen bij Apple. Bevat je public key. |
| Private Key | Een geheime key die je lokaal genereert en in je Keychain bewaart. |
| Signing Certificate | Uitgereikt door Apple. Koppelt je public key aan je identiteit als developer. |
| Provisioning Profile | Een bestand dat je certificate, app ID, entitlements en doeltoestellen aan elkaar koppelt. |
| Entitlements | Speciale rechten die je app aanvraagt (zoals Push, iCloud, App Groups, enz.). |

## De flow: stap voor stap

We overlopen het signingproces:

### 1️⃣ Je genereert een key pair

- Op je Mac maak je een private/public key pair aan.
- De private key blijft op je toestel (in je Keychain).
- De public key wordt opgenomen in een **Certificate Signing Request (CSR)**.

### 2️⃣ Apple reikt een signing certificate uit

- Je uploadt de CSR naar Apple via het Developer Portal (of Xcode doet het voor je).
- Apple verifieert je Developer Account en reikt een **Signing Certificate** uit.
- Het certificate bevat:
   - Je public key.
   - Je identiteit (developer of team).
   - De digitale handtekening van Apple (die bewijst dat het een geldig certificate van Apple is).

### 3️⃣ Je bouwt je app

Wanneer je je app compileert:

- Xcode gebruikt je private key om de app bundle te signen.
- De handtekening bewijst dat de app van jou komt en dat de code sinds het signen niet veranderd is.

### 4️⃣ Je maakt een provisioning profile aan

- Een **Provisioning Profile** combineert:
   - De **Bundle ID** van de app (je App ID).
   - Je **Signing Certificate**.
   - De UDID's van de toestellen (voor development profiles).
   - Alle ingeschakelde entitlements.
- Het profile vertelt iOS: *"Deze app mag op dit toestel draaien en komt van deze geautoriseerde developer."*

### 5️⃣ Het profile wordt ingebed

- Het provisioning profile wordt in de app bundle ingebed.
- Wanneer de app start, controleert iOS of:
   - de app gesigned is met de bijhorende private key.
   - het certificate nog geldig is.
   - het profile toelaat dat de app op dit toestel draait.
   - de entitlements overeenkomen.

## Kort overzicht: soorten certificates

| Soort certificate | Doel |
| --- | --- |
| Development Certificate | Om te debuggen op echte toestellen tijdens de ontwikkeling. |
| Distribution Certificate | Voor TestFlight, de App Store of Enterprise deployment. |
| Enterprise Certificate | Voor interne bedrijfsapps die buiten de App Store verspreid worden (vereist een speciale account). |

## Kort overzicht: soorten provisioning profiles

| Soort profile | Gebruikt voor |
| --- | --- |
| Development | De app installeren op geregistreerde toestellen om te testen. |
| Ad Hoc | De app buiten de App Store delen met een beperkt aantal toestellen. |
| App Store | Indienen bij de App Store of TestFlight. |
| Enterprise | Interne verspreiding binnen je bedrijf. |

## Private keys: de zwakke schakel

- De **private key** is het gevoeligste onderdeel.
- Zonder die key kun je geen nieuwe builds signen.
- Verlies je hem, dan moet je het certificate intrekken en een nieuw aanmaken.
- Daarom waarschuwt Apple vaak: *"Bewaar je private keys veilig en maak er een back-up van."*

👉 Gebruik je meerdere Macs? Exporteer en importeer dan de private key + het certificate om problemen met signen te vermijden.

## Vereenvoudigd schema

```
[ Private Key (your Mac) ] <--signs--> [ App Bundle ]
		↓
[ Public Certificate (issued by Apple) ]
		↓
[ Provisioning Profile (rules + entitlements) ]       
		↓
[ iOS Device: validates everything ]
```

## Moderne bonus: Xcode & automatic signing

- Xcode probeert veel hiervan te automatiseren.
- Wanneer “Automatically Manage Signing” aanstaat, doet Xcode het volgende:
   - CSR's genereren.
   - Provisioning profiles aanmaken.
   - Certificates downloaden.
   - Profiles synchroniseren.
- Voor veel developers verbergt dat het grootste deel van de complexiteit.
- MAAR: wanneer er iets misloopt (of in CI/CD-pipelines), is het van onschatbare waarde dat je het manuele proces begrijpt.

## Valkuilen om te vermijden

- ✅ Maak altijd een back-up van je private key.
- ✅ Trek oude certificates in die je niet meer nodig hebt.
- ✅ Let op provisioning profiles die vervallen.
- ✅ Voor CI/CD: bewaar certificates en private keys op een veilige manier.

## Zet je perfecte CI/CD op

In de meeste lokale development workflows regelt Xcode dit automatisch achter de schermen. Maar zodra je overstapt op CI/CD-pipelines, automatisering, fastlane, de [impaktfull_cli](https://www.impaktfull.com/blog/the-power-of-custom-clis) of andere geavanceerde releaseprocessen, moet je bijna altijd expliciet een `exportOptions.plist`-bestand meegeven om het exportgedrag te bepalen en interactieve prompts te vermijden.

### Voorbeeld voor de App Store

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>app-store</string>
    <key>uploadBitcode</key>
    <false/>
    <key>uploadSymbols</key>
    <true/>    
    <key>signingStyle</key>
    <string>manual</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>com.yourcompany.yourapp</key>
        <string>Your_Provisioning_Profile_Name</string>
    </dict>
    <key>teamID</key>
    <string>YOUR_TEAM_ID</string>
</dict>
</plist>
```

### Voorbeeld voor Ad Hoc

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>ad-hoc</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>com.yourcompany.yourapp</key>
        <string>Your_Provisioning_Profile_Name</string>
    </dict>
    <key>teamID</key>
    <string>YOUR_TEAM_ID</string>
</dict>
</plist>
```

### Hoe gebruik je de export options?

```
xcodebuild -exportArchive \
  -archivePath path/to/YourApp.xcarchive \
  -exportOptionsPlist path/to/exportOptions.plist \
  -exportPath path/to/exported/ipa
```

## App signing bij impaktfull

We willen zoveel mogelijk controle over onze signing flow. Daarom kiezen we voor alpha, beta en productie altijd voor manual signing. Voor development is het gewoon makkelijker om snel dingen uit te testen, dus daar zetten we automatic signing aan.

Je private keys deel je op een veilige manier. Daarom is het gebruik van [1password](https://www.impaktfull.com/blog/choosing-the-right-tool-for-the-job-our-path-to-build-high-quality-custom-apps) en de [impaktfull_cli](https://www.impaktfull.com/blog/the-power-of-custom-clis) om builds te maken superbelangrijk voor onze CI/CD-flow. Zo kunnen we een nieuwe private key aanmaken die meteen beschikbaar is op alle CI/CD-runners.

## Conclusie

Het signingsysteem van Apple is streng, maar met goede reden: het zorgt voor veiligheid, vertrouwen en de integriteit van apps op miljoenen toestellen. In het begin is het verwarrend, maar zodra je de bouwstenen begrijpt (certificates, keys en profiles), begint het te kloppen.

Wil je dit zo opgezet voor je team, met signing die op elke Mac en elke CI-runner hetzelfde werkt? We zetten [app-releases](https://www.impaktfull.com/service/apps) zo op voor elke app die we bouwen, en controleren bestaande pipelines in een [health check](https://www.impaktfull.com/service/health-checks).

---

impaktfull bouwt en beheert apps, websites, platformen en AI-agents, vanuit Antwerpen. Meer op https://www.impaktfull.com/nl.
