Подпись приложений для iOS: от сертификатов до публикации в App Store

Без правильной подписи ваше iOS-приложение не запустится даже на тестовом устройстве — система заблокирует его с ошибкой Failed to verify code signature или App installation failed. Процесс подписи связывает бинарный файл (.ipa) с уникальным идентификатором разработчика (Developer ID), сертификатами и профилями provisioning, которые Apple проверяет при установке. Если вы видите в Xcode предупреждение No signing certificate found или в Organizer красной строкой подсвечивается Missing Provisioning Profile, значит, на одном из этапов подписи произошла ошибка — чаще всего из-за неверно сгенерированного сертификата или несоответствия Bundle ID.

Подпись для iOS отличается от Android тем, что требует обязательной привязки к Apple Developer Account (стоимость — $99/год) и проходит через строгий контроль компании. Даже для тестирования на физическом устройстве (Ad Hoc или Development) нужен действующий сертификат, а для публикации в App Store — отдельный Distribution Certificate и профиль App Store Provisioning Profile. В этой статье разберём все этапы: от генерации сертификатов в Keychain Access до загрузки подписанного .ipa через Transporter или Xcode Organizer.

1. Типы подписи iOS-приложений: когда какой использовать

Apple предлагает четыре основных способа подписи, каждый из которых предназначен для конкретной задачи. Выбор неправильного типа — одна из главных причин ошибок при установке или публикации.

  • 🔧 Development — для отладки на подключённых устройствах через Xcode. Требует Development Certificate и профиль с указанием UDID устройств. Срок действия — 1 год.
  • 📱 Ad Hoc — для тестирования на ограниченном числе устройств (до 100) без App Store. Использует Distribution Certificate, но профиль привязан к конкретным UDID.
  • 🌍 App Store — для публикации в магазине. Подпись проходит через Apple’s servers при загрузке .ipa. Требует Distribution Certificate и профиль без привязки к устройствам.
  • 🏢 Enterprise — для внутреннего распространения в компаниях (через MDM или прямую установку). Сертификат стоит $299/год и позволяет обходить App Store.

Например, если вы пытаетесь загрузить приложение в TestFlight с профилем Ad Hoc, получите ошибку Invalid Provisioning Profile. А при использовании Development Certificate для архивации в Xcode с целью публикации в App Store — предупреждение No suitable application records were found.

2. Шаг 1: Создание сертификатов в Apple Developer Account

Сертификаты — основа подписи. Они подтверждают, что приложение создано доверенным разработчиком. Без действующего сертификата Xcode не сможет скомпилировать проект для устройства.

  1. Генерация CSR-файла

    Откройте Keychain Access на Mac → Certificate AssistantRequest a Certificate from a Certificate Authority. Укажите email (должен совпадать с Apple ID) и сохраните .certSigningRequest файл.

  2. Загрузка CSR в Developer Account

    Перейдите в Apple Developer AccountCertificates, Identifiers & ProfilesCertificates → нажмите +. Выберите тип сертификата (Apple Development или Apple Distribution) и загрузите .certSigningRequest.

  3. Установка сертификата

    После генерации скачайте .cer-файл и дважды кликните для установки в Keychain Access. Проверьте, что сертификат отображается в разделе My Certificates.

Ошибка No valid signing identities found в Xcode означает, что сертификат не установлен или просрочен. Чтобы исправить, удалите старый сертификат из Keychain и повторите процедуру. Срок действия сертификатов — 1 год, после чего их нужно обновлять.

Сертификат отображается в Keychain Access|Срок действия не истёк (проверьте в "Get Info")|Email в CSR совпадает с Apple ID|Тип сертификата соответствует цели (Development/Distribution)-->

3. Шаг 2: Регистрация App ID и настройка Bundle ID

App ID (или Bundle ID) — уникальный идентификатор приложения в экосистеме Apple. Он должен совпадать в трех местах: в Xcode (поле Bundle Identifier в Info.plist), в Developer Account и в профиле provisioning. Расхождение приведёт к ошибке Bundle Identifier does not match.

  • 📝 Формат Bundle ID: обычно используется обратная DNS-запись, например com.yourcompany.appname. Изменить его после публикации в App Store нельзя.
  • 🔗 Wildcard App ID: можно использовать (например, com.yourcompany.) для тестирования, но для App Store требуется явный Bundle ID.
  • 🔄 Explicit App ID: нужен для Push-уведомлений, Game Center и других сервисов Apple. Регистрируется вручную в Developer Account.

Чтобы зарегистрировать App ID:

  1. Перейдите в Identifiers → нажмите + → выберите App IDs.
  2. Укажите описание (например, "MyApp Production") и Bundle ID (explicit или wildcard).
  3. Выберите нужные App Services (например, Push Notifications) и сохраните.
Что делать, если Bundle ID уже занят?

Если вы видите ошибку An App ID with Identifier 'X' is not available, значит, этот ID уже используется другим приложением в вашем аккаунте или чужим. Решения:

1. Измените суффикс (например, com.yourcompany.appname2).

2. Если ID занят вашим старым приложением — удалите его в Developer Account (вкладка App IDs).

3. Для wildcard-конфликтов проверьте, не зарегистрирован ли com.yourcompany.* ранее.

4. Шаг 3: Создание Provisioning Profile

Профиль provisioning связывает сертификаты, App ID и устройства (для Development/Ad Hoc). Без него Xcode не сможет подписать приложение. Ошибка Provisioning profile 'X' doesn't include the currently selected device означает, что UDID устройства не добавлен в профиль.

Тип профиля Связанные сертификаты Устройства Использование
Development Apple Development До 100 устройств (UDID) Отладка через Xcode
Ad Hoc Apple Distribution До 100 устройств (UDID) Тестирование без App Store
App Store Apple Distribution Нет привязки Публикация в магазине
Enterprise Apple Distribution (Enterprise) Нет привязки Внутреннее распространение

Чтобы создать профиль:

  1. В Developer Account перейдите в Profiles → нажмите +.
  2. Выберите тип профиля (App Store, Ad Hoc и т.д.).
  3. Укажите App ID, сертификаты и устройства (для Development/Ad Hoc).
  4. Скачайте профиль (.mobileprovision) и перетащите его в Xcode или установите через двойной клик.
📊 Какой тип provisioning profile вы используете чаще?
Development
Ad Hoc
App Store
Enterprise

5. Шаг 4: Настройка подписи в Xcode

После подготовки сертификатов и профилей нужно привязать их к проекту в Xcode. Если конфигурация неверна, при архивации появится ошибка No profiles for 'com.your.bundle' were found.

Инструкция:

  1. Откройте проект в Xcode → выберите цель (Target) → вкладка Signing & Capabilities.
  2. В поле Team выберите ваш Apple Developer Account.
  3. В Bundle Identifier укажите зарегистрированный App ID.
  4. В разделе Signing Certificate выберите Automatically manage signing (рекомендуется) или вручную укажите профиль (Provisioning Profile).

Если Xcode не видит профили, обновите их через PreferencesAccounts → выберите аккаунт → Download All Profiles. Для ручной подписи используйте команду в Terminal:

security find-identity -v -p codesigning

Эта команда покажет все установленные сертификаты. Если список пуст — сертификаты не установлены.

6. Шаг 5: Архивация и экспорт приложения

После успешной настройки подписи можно архивировать проект для распространения. В зависимости от цели выберите один из форматов экспорта:

  • 📦 Development — для отладки на устройствах через Xcode (не создаёт .ipa).
  • 📱 Ad Hoc — генерирует .ipa для установки на зарегистрированные устройства (например, через TestFlight или Diawi).
  • 🌍 App Store — создаёт .ipa для загрузки в App Store Connect.
  • 🏢 Enterprise — для внутреннего распространения (требует Enterprise Account).

Чтобы архивировать проект:

  1. В Xcode выберите схему (Scheme) → Generic iOS Device.
  2. Нажмите ProductArchive. Если появится ошибка No signing certificate found, вернитесь к шагу 4.
  3. После архивации откройте Organizer → выберите архив → Distribute App.
  4. Укажите метод распространения (App Store Connect, Ad Hoc и т.д.) и следуйте инструкциям.

Для загрузки в App Store используйте Transporter (утилита от Apple) или загрузите .ipa через App Store Connect. Перед отправкой проверьте подпись командой:

codesign -dv --verbose=4 /путь/к/вашему.app

В выводе должен быть ваш Team Identifier и статус valid on disk.

7. Распространённые ошибки подписи и их решения

Даже опытные разработчики сталкиваются с проблемами подписи. Вот самые частотные ошибки и способы их исправления:

Ошибка Причина Решение
No signing certificate found Отсутствует или просрочен сертификат Сгенерируйте новый сертификат в Developer Account и установите его
Provisioning profile not found Профиль не загружен в Xcode или не совпадает Bundle ID Скачайте профиль с Developer Account и перетащите в Xcode
App installation failed: A signed resource has been added, modified, or deleted Изменение файлов после подписи (например, добавление ресурсов) Очистите проект (ProductClean Build Folder) и переархивируйте
The executable was signed with invalid entitlements Несоответствие Entitlements в профиле и проекте Проверьте .entitlements файл и права в профиле (Keychain Sharing, Push Notifications)

Критическая ошибка: если вы видите errSecInternalComponent при попытке подписать приложение, это означает системный сбой в Keychain Access. Решение:

  1. Удалите все сертификаты и профили из Keychain и Xcode.
  2. Перезагрузите Mac.
  3. Повторно установите сертификаты и профили.
Как проверить, какие entitlements использует ваше приложение?

Запустите в Terminal:

codesign -d --entitlements - /путь/к/вашему.app

Эта команда выведет все права (keychain-access-groups, aps-environment и др.), которые должны совпадать с профилем.

8. Альтернативные способы подписи: без Mac и Xcode

Если у вас нет доступа к Mac или Xcode, можно подписать приложение альтернативными методами, но с ограничениями:

  • 🖥️ Online-сервисы (например, AppCenter, Bitrise): позволяют собирать и подписывать проекты в облаке, но требуют загрузки исходников и конфигурации сертификатов.
  • 🐍 Fastlane: инструмент для автоматизации (включает gym для сборки и pilot для загрузки в TestFlight). Требует предварительной настройки fastlane и Ruby.
  • 📦 Ручная подпись через командную строку:
    xcrun altool --upload-app -f app.ipa -u apple_id -p password

    (устарело с 2020 года, заменено на notarytool для нотаризации).

Для нотаризации приложений (обязательно с macOS Catalina и новее) используйте:

xcrun notarytool submit app.zip --apple-id apple_id --password app-specific-password --team-id TEAM_ID

FAQ: Частые вопросы о подписи iOS-приложений

Можно ли подписать приложение без платы за Apple Developer Program?

Нет. Для установки на физическое устройство или публикации в App Store требуется действующая подписка ($99/год). Бесплатный аккаунт позволяет собирать приложения только для симулятора или через TestFlight (с ограничениями).

Что делать, если истёк сертификат, а приложение уже в App Store?

Приложения в App Store остаются работоспособными даже после истечения сертификата, так как подпись проверяется при загрузке, а не при установке пользователем. Однако для обновлений нужно продлить сертификат и перезагрузить бинарник.

Как подписать приложение для Enterprise-распространения?

Нужен Apple Enterprise Developer Account ($299/год). Процесс аналогичен Ad Hoc, но профиль не привязан к устройствам. Приложение распространяется через внутренний портал или MDM (например, Jamf или MobileIron).

Почему после обновления Xcode перестала работать подпись?

Новые версии Xcode могут сбрасывать настройки подписи. Проверьте:

  1. В PreferencesAccounts обновите профили (Download All Profiles).
  2. В проекте переключите Signing Certificate на Automatically manage signing и обратно.
  3. Удалите папку ~/Library/MobileDevice/Provisioning Profiles и перезагрузите Xcode.

Можно ли использовать один сертификат для нескольких приложений?

Да, один Development или Distribution сертификат можно использовать для всех приложений в вашем аккаунте. Однако каждый Bundle ID должен быть зарегистрирован отдельно, и для него нужен свой профиль provisioning.

Если после прочтения статьи остались вопросы по конкретной ошибке подписи — уточните текст ошибки из Xcode или Terminal, а также версию macOS и Xcode. Это поможет точнее диагностировать проблему.