LODY/정리

애플 플랫폼 백과사전 / iOS 코드 서명 정리

iOS 코드 서명 정리

서명이 하는 일

  • 앱의 출처(등록된 개발자·조직)를 검증
  • 서명 이후 코드 변조 여부 검증
  • Push Notification · App Groups 같은 권한 사용 가능 앱 제한

코드 서명의 세 요소

  • Certificate
  • App ID
  • Provisioning Profile

이 셋은 개별로 쓰이지 않는다. Provisioning Profile이 묶는 단위.

Provisioning Profile
├── App ID (Bundle Identifier)
├── Certificate
├── Devices (Ad Hoc 한정)
└── Entitlements (Push, App Groups 등)

Certificate와 P12

  • Certificate: Apple Developer Program 소속을 증명하는 공개키 증명서
  • 생성 흐름: 키 쌍 → CSR → Apple 업로드 → .cer 발급 → private key와 묶어 .p12 생성
  • CI에 필요한 건 .cer이 아니라 .p12 (private key 포함). 서명을 검증이 아니라 생성해야 함
# .cer -> PEM
openssl x509 -inform DER -in distribution.cer -out distribution.pem
 
# 인증서 + private key -> P12
openssl pkcs12 -export \
  -out distribution.p12 \
  -inkey private_key.key \
  -in distribution.pem

Provisioning Profile

담는 정보:

  • App ID
  • 허용된 Certificate
  • Entitlement 목록
  • Ad Hoc 한정 기기 UUID 목록

같은 앱이라도 Staging vs Production이 서로 다른 프로파일을 씀.

Staging (Ad Hoc)
→ Distribution Certificate
→ Bundle ID
→ 등록된 테스트 기기 UUID
→ 내부 테스트용 권한 조합
 
Production (App Store / TestFlight)
→ Distribution Certificate
→ Bundle ID
→ 기기 UUID 없음
→ 배포용 권한 조합

프로파일 덤프:

security cms -D -i Sendy_Staging_AdHoc.mobileprovision

자주 보는 필드: ExpirationDate, application-identifier, DeveloperCertificates, Entitlements.


Ad Hoc 프로파일

  • 테스트 기기 UUID가 프로파일 안에 들어감 → 기기 추가 시 프로파일 재생성
  • 배포 자동화에서 sigh --force가 필요한 배경
  • App Store/TestFlight 프로파일은 기기 UUID 없음 → 이 문제 없음

로컬 Xcode vs CI

Keychain 인증서프로파일 갱신Signing
로컬 Xcode존재Automatic 가능Automatic Signing
CI 러너비어 있음P12·프로파일 직접 배치export 옵션 명시 필요

로컬에서 되는데 CI에서 실패하는 경우의 원인은 거의 이 차이.


주요 에러 → 원인 매핑

에러원인
No signing certificate foundKeychain에 P12 없음 / import 실패
Provisioning profile doesn't include signing certificate프로파일이 현재 인증서 미포함
No profiles for ... were foundApp ID 또는 export method 매칭 프로파일 없음
requires a provisioning profilearchive 이후 export 단계에서 method/profile 매핑 누락

CI에 올릴 때 체크리스트

  • .p12 + 비밀번호 Secret 등록
  • 프로파일 .mobileprovision 배치 경로 고정
  • Keychain 임시 생성 + P12 import
  • ExportOptions.plist에 method·teamID·profile 매핑 명시
  • 프로파일 만료일 사전 확인
  • Staging / Production 별 프로파일 분리