[iOS] Certificate 와 Provisioning profile
개-하! 오늘은 예전 컨퍼런스에서 “Certificate 와 Provisioning profile” 주제로 발표한 내용을 고대로 텍스트로 옮겨보려고 합니다.
어떻게 코드 서명이 앱의 무결성을 보장하는가 등 발표 시간 때문에 빠졌던 내용이 조금 더 추가로 들어갈 수도 있지만, 그 부분을 제외하면 발표 스크립트와 크게 다를 바 없는데여, 동영상도 있지만 굳이~ 글로 다시 쓰는 이유는.. 동영상은 다시 보기 귀찮잖아요? 하지만 글은 키워드로 찾기도 좋고.. 슉슉 넘길수도 있으니까.. 미래의 저를 위해서라고 할 수 있져 ㅎ
나는 글자 못읽는다! 하면 영상을 봐주시고, 영상을 못본다! 하면 이 글로 내용을 확인해주시면 될 것 같습니다. 만약 둘다 싫다면..? 유감..!
유투브 영상
발표 자료
그럼 미루고 미뤄왔던 발표 내용 정리! 연휴를 맞아 시작해보져 ㄱㄱ
들어가기 전에
우선 Certificate? Provisioning Profile? 이 뭘까요..? 왜 필요할까요..? 우리는 이걸 언제 쓰고 있었던건지,, 아니,, 쓰고는 있던걸까요?
“🤔 엥?? 저런거 없이 나는 잘만 개발해 왔는데??” 라고 하는 분도 계실테고,,,
“🤔 흠.. 엑스코드 어딘가에 저런게 있었던 것도 같구~~~” 하시는 분도 계실것 같습니다.
그 중 대부분은 Automatically manage signing
이 체크 되어있을테고,
Archive 후 App Store, Ad Hoc, Enterprise 와 같은 배포 방법에 따라
앱을 Re-Sign 할때도 아마 Automatically manage signing
이 체크된 채로 Next 를 누르셨을거예요
이 옵션이 체크 되어있으면 Xcode 는 자동으로 profile, app ID, certificate 를 생성 및 업데이트하는데요, 그러니까 사실은 내가 인지하지 못했더라도 Certificate 및 Provisioning Profile 을 사용하고 있었던거겠죠??
이렇게 무심코 클릭 클릭으로 넘어갔을때, Xcode 의 뒤에서는 과연 어떤 일들이 일어나고 있던건지 살펴보겠습니다.
Certificate
간단한 질문 하나로 시작해볼게여.
혹시 여기 제가 만든 “NaljinApp” 깔아보실 분 계신가요? 하면 어떤 생각이 드시나요?
“🙂 아 우리 사이에 당연히 믿고 깔져~” 하는 분도 계시겠지만, 대부분 상황에서는 “🙄 누구세요… 안사요..” 라고 말할 것 같은디요!
그럼 어떻게 해야 이 앱이 믿고 설치할만한 앱이라는 것을 증명할 수 있을까요?
현실 세계의 서명
이해를 돕기 위해서 잠시 현실의 예를 들어보겠습니다. (참고 — iOS 앱 서명 개요)
현실에서 우리는 다양한 상황에 대해 계약서를 작성하는데요, 저는 요즘 살려고 운동하는 중이라, PT 계약서를 임의로 만들어봤습니다.
그리고 계약서에 싸인을 해야겠죠?
이 싸인, 즉 서명을 통해 우리는 서명의 당사자를 확인하고, 이후에는 계약 조항을 변경할 수 없다는 사실을 서로 합의합니다.
코드 서명
이와 비슷하게 코드 서명은 말 그대로 코드를 디지털 서명하는 과정을 뜻합니다. 이를 통해 누가 코드를 작성했는지 확인하고 서명 이후에는 코드가 변경되지 않았다는 사실을 보증 할 수 있습니다.
이런 코드 서명 방식은 iOS 뿐만 아니라, 소프트웨어 보안에서 널리 사용되는 보편적인 개념입니다.
코드 서명은 공개 키, 개인 키, 인증서와 같은 다양한 보안 용어를 사용하는데요
우선은 코드 서명의 동작 원리를 깊게 설명하기 보다, “iOS 에서 코드 서명을 하기 위해서는 어떤 과정이 필요한가” 를 중점적으로 살펴보겠습니다.
애플 발급 인증서
자 여기까지 이해했으면 코드 서명 내용은 잠깐 뒤로 하고, 현실의 다른 상황으로 돌아와보겠습니다.
현실에서 누군가 “너가 개발에 필요한 지식을 갖고 있는 사람인지 증명해봐!” 라고 한다면, 어떤 자료를 가져갈 것 같으신가요?
저라면 졸업 증명서나, 재직 증명서 등의 문서를 가져갈 것 같은데요, 이는 즉 학교나 회사라는 믿을 수 있는 권위를 빌려서, “저는 여기서 개발 관련 증명서를 떼주니까 믿을 수 있는 사람이에요~~” 라는 의미가 담겨있는 셈입니다.
인증서는 일반적으로 신뢰할 수 있는 기관에서 제공할 때 더 강력한데요, 이 사실은 애플 세계에서도 동일하게 적용됩니다.
애플 세계에서는 신뢰할 수 있는 기관인 Apple 에서 인증서를 받습니다. 즉, 이 인증서를 통해 “애플이 나를 합법적인 개발자로 인정함!”을 증명할 수 있는 것입니다.
실제로 애플에서 인증서를 발급받기 위해서는 키체인에서 “인증 기관에 인증서 요청”을 클릭하고
필요한 정보를 채우면
Certificate Siging Request, 즉 CSR 이라고하는 인증 서명 요청을 다운 받을 수 있습니다.
이 파일은 쉽게 말해 “인증서 발급을 위해 필요한 정보를 담고 있는 데이터” 입니다. “나는 이런 사람이고, 이 공개키가 포함된 인증서를 만들고 싶다!” 라는 내용이 들어있는, 일종의 인증서를 위한 신청서인 셈이죠.
여기서 말하는 공개키는, CSR 파일을 만들때 키체인에서 자동으로 생성하는 공개 키 — 개인 키 키 쌍 중, 공개키를 말합니다.
참고로 CSR 을 만들때 생성되는 키 쌍에 대한 정보도 지정을 할 수 있습니다. 기본적으로 키 크기는 2048 비트, 알고리즘은 RSA 로 설정이 되어있습니다.
이제 신청서를 다 작성했으니까, 진짜 인증서를 발급 받으러 가보겠습니다.
기본적으로 인증서는 Apple Developer Program 에 가입된 사람들만 신청을 할 수 있습니다.
물론 Apple ID로 Xcode 에 로그인하고 Personal Team이라고 하는 무료 계정을 통해 실제 기기에서 앱을 테스트할 수도 있습니다. 하지만 이 무료 계정은 제한된 수의 앱을 몇 개의 기기에만 배포할 수 있고, 앱들은 며칠 후에 만료되므로 이 부분은 논외로 하겠습니다. (참고 — App Distribution — From Ad-hoc to Enterprise)
애플 개발자 사이트에서 확인할 수 있는 인증서 유형은 개발, 배포, 푸시 알림, 애플 월렛 등으로 다양하지만
여기서 저희는 Apple Development 와 Apple Distribution 에 집중해보겠습니다.
Apple Development 인증서는 Xcode 11 이후부터 iOS, macOS, tvOS, watchOS 같은 앱들의 development version 을 서명하는데 사용합니다.
Apple Distribution 인증서는 Xcode 11 이후부터 App Store 제출용이나 Ad Hoc 등 배포 용도의 앱들을 서명하는데 사용됩니다.
참고로 Enterprise 계정은 Apple Distribution 항목 대신, In-House and Ad Hoc 이라는 항목이 있습니다.
하지만 우선 일반적인 개발자 계정일때의 상황에 집중해보겠습니다.
Run 을 하든 Archive 하든, 기본적으로 프로젝트를 빌드할 때 필요한 인증서는 Development 인증서입니다. (참고 — Distribute apps in Xcode with cloud signing)
따라서 발급 받을 인증서의 종류를 Apple Development 로 선택하고,
신청서 업로드를 통해
생성된 인증서를 다운로드 받으면
이렇게 애플에서 발급한 인증서 파일을 하나 얻을 수 있습니다
이 인증서를 더블 클릭해서 로컬에 설치하면, Keychain 쪽에 아까 인증서 요청을 할때 생성된 개인 키와 합쳐져 하나의 Signing Certificate (서명 인증서) 가 됩니다.
여기서 플로우를 놓치신 분들을 위해 잠깐 멈춰가겠습니다.
그러니까 처음에 코드 서명을 설명하더니, 갑자기 애플에서 인증서 발급 받는 얘기를 하고 이게 결국 개인 키랑 합쳐져서 서명 인증서가 됐다구??
라고 생각하시면 잘 따라오고 계신거예요.
왜냐하면 이 “서명 인증서”를 가지고 “코드 서명”을 하기 때문입니다
Signing Certificate, 즉 서명 인증서는 한마디로 코드 서명에 사용되는 digital identity 라고 정의할 수 있습니다. (참고 — What is app signing?)
서명 인증서
서명 인증서를 조금 더 자세히 살펴볼까요?
먼저 Apple 에서 발급한 인증서에는 기본적으로 public key 를 포함해 CSR 을 생성하는 동안 제공한 모든 데이터와, 만료 날짜, 발급자 정보와 같은 추가 데이터가 포함됩니다.
실제로 키체인에서 인증서 클릭을 해보면 아래와 같은 온갖 데이터가 명시된 화면을 확인할 수 있습니다.
그 다음 개인 키는 암호화 기능에서 서명을 생성하는 데 사용됩니다. (참고 — Understanding the Code Signature)
이렇게 애플에서 발급한 인증서와, 개인키가 합쳐져서 하나의 서명 인증서가 됩니다
우리는 이렇게 생성된 서명 인증서를 사용해서 앱을 서명하고, 시스템은 유효한 서명을 통해 누가 앱에 서명했는지 식별하고 앱이 서명된 이후 수정되지 않았다는 것을 확인할 수 있습니다. (참고 — What is app signing?)
지금까지의 과정을 살펴보면
- 엑스코드에서 요청으로
- 키체인에서 CSR 을 만들고
- 애플에 인증서를 요청해서
- 다운받은 후에 키체인에 서명 인증서를 형성합니다
더 자세한 코드 서명의 내용은 오늘 주제의 범위를 넘어가긴 하지만 Understanding the Code Signature 에 나오는 코드 서명의 흥미로운 내용에 대해 좀 더 살펴보겠습니다. 어떻게 코드 서명이 앱의 무결성을 보장할 수 있다는 걸까여?? (여기는 안봐도 크게 상관은 없어서, 이 글 흐름이 끊기고 싶지 않다!! 하면 Provisioning Profile 섹션으로 바로 넘어가세요!)
모든 경우에 코드 서명은 세 부분으로 구성됩니다
- Seal : 코드 서명 소프트웨어에 의해 생성된, 코드의 다양한 부분에 대한 체크섬 또는 해시의 모음 입니다. seal 은 변경(alterations)을 감지하는데 사용될 수 있습니다.
- Digital signature : 코드 서명 소프트웨어는 서명자의 신원(signer’s identity)을 이용해 seal 을 암호화해 디지털 서명을 생성합니다. 이것은 seal 의 무결성(intergrity)를 보장합니다.
- Code requirements. 코드 서명의 검증(verification)을 지배(governing)하는 규칙들입니다.
Seal
코드 서명 소프트웨어는 단방향 해싱 알고리즘을 통해 실행 파일, 리소스, Info.plist 파일, 코드 요구 사항(code requirements) 등 최종 번들의 여러 부분(앱, 라이브러리 또는 프레임워크)을 실행하여 seal을 생성합니다. 이렇게 하면 특정 input 블록에 고유하지만, 원래 input 을 재구성하는 데 사용할 수 없는 짧은 숫자 문자열인 일련의 다이제스트 또는 체크섬이 생성됩니다.
평가 중인 코드와 해당 해시 컬렉션을 모두 가진 검증 엔티티(verifying entity)는 서명자와 정확히 같은 방식으로 코드에 대해 동일한 해시 알고리즘을 실행하고 결과를 원래 저장된 해시와 비교하여 변경된 것이 있는지 확인합니다. 코드를 조금만 수정해도 다이제스트가 달라져 변조 또는 손상을 나타냅니다. 그러나 이 검증은 저장된 해시의 신뢰성만큼만 신뢰할 수 있습니다. 디지털 서명이 이를 보장합니다.
Digital Signature
Security Overview에 설명되어있는 것과 같이 디지털 서명은 공개 키 암호화를 사용하여 데이터 무결성(integrity)을 보장합니다. 종이에 잉크로 쓴 서명처럼 디지털 서명을 이용해 서명자를 식별하고 인증할 수 있습니다. 그러나 디지털 서명은 위조하기가 더 어렵고 한 걸음 더 나아가서 서명된 데이터가 변경되지 않았음을 보장할 수 있습니다. 이것은 누군가가 쓴 돈의 액수를 바꾸면 종이 위에 “무효”라는 글자가 있는 워터마크가 보이게 하는 방식으로 수표를 디자인하는 것과 어느 정도 비슷합니다.
코드 서명의 맥락에서, 서명 소프트웨어는 서명자의 개인 키로 seal 의 해시를 암호화함으로써 디지털 서명을 생성합니다. 서명인만 개인 키를 소유하므로 서명인만 이 암호화를 수행할 수 있습니다. 이는 즉, 서명자가 일치하는 인증서(matching certificate)와 함께 앱(또는 프레임워크, 아카이브 또는 기타 서명된 개체)에 저장하는 암호화된 해시 컬렉션으로, 모여서 디지털 서명을 나타냅니다.
서명(signature)을 검증하기 위해 검증 소프트웨어는 다양한 코드 및 데이터 블록에 걸쳐 동일한 해시 집합을 계산합니다. 그런 다음 인증서에 내장된 서명자의 공개 키를 사용하여 코드와 함께 제공된 암호화된 해시를 해독하여 서명자가 계산한 원래 해시를 얻습니다. 두 해시가 일치하는 경우 서명자의 개인 키를 소유한 사람이 서명한 이후 데이터가 수정되지 않았음을 알 수 있습니다.
서명된 코드는 아래와 같은 여러 가지 디지털 서명이 포함될 수 있습니다
- 코드가 범용(universal)이면 각 슬라이스(아키텍처)의 object 코드가 별도로 서명됩니다. 이 서명은 바이너리 파일 자체에 저장됩니다.
- 응용 프로그램 번들의 다양한 데이터 구성 요소(예:
Info.plist
)도 서명됩니다. 이러한 서명은 번들 내의_CodeSignature/CodeResources
라는 파일에 저장됩니다. - 앱에 내장된 라이브러리, helper tools 및 기타 코드 bits 와 같은 중첩된 코드는 자체적으로 서명되며, 해당 서명은 또한 번들 내의
_CodeSignature/CodeResources
에 저장됩니다.
Code Requirements
Code requirements 는 macOS가 코드 서명을 평가하기 위해 사용하는 규칙입니다. 평가를 수행하는 시스템은 목표에 따라 평가 시 어떤 코드 요구사항을 적용할지 결정합니다. 예를 들어, Gatekeeper 에는 앱을 처음 시작할 수 있도록 허용하기 전에, Mac 앱 스토어 또는 개발자 ID 인증서로 서명해야 하는 규칙이 있습니다. 다른 예로, 앱은 해당 앱에서 사용하는 모든 플러그인이 Apple에 의해 서명되어야 한다는 코드 요구사항을 적용할 수 있습니다.
서명자가 지정하고 코드 서명의 일부로 포함되는 코드 요구사항을 내부 요구사항(internal requirements)이라고 합니다. 이는 코드 서명을 확인하는 시스템에서 사용할 수 있지만, 시스템에서 사용할지 여부를 선택할 수 있습니다. 이전 예제의 앱 플러그인에는 자체 내부 요구사항이 있을 수 있지만, 이를 적용할지 여부는 플러그인을 사용하는 앱인 평가 시스템에 달려 있습니다. 왜냐하면 seal이 코드 요구 사항을 포괄하기 때문에, 서명이 유효한 한 내부 요건도 온전할 것이 확실하기 때문입니다.
가장 중요한 내부 요구사항은 지정된 요구사항(designated requirement) 즉, DR 입니다. 이 규칙은 평가 시스템에 특정 코드 조각을 식별하는 방법을 알려줍니다. 동일한 DR을 가진 성공적으로 검증된 두 개의 코드는 동일한 코드로 간주됩니다. 이를 통해 코드 서명자는 동일한 앱으로 처리되는 앱의 새 버전을 게시할 수 있습니다. 예를 들어, 애플 메일의 DR은 “Apple 에 의해 서명되었고, com.apple.Mail
identifier 를 가짐" 일 수 있습니다. 앱의 새 버전이 게시될 때, 앱의 새 버전이 동일한 DR을 갖는 한, 바이너리 실행 파일이 완전히 다르더라도 똑같은 애플 메일로 간주됩니다. 게다가, 오직 애플만이 애플로서 서명할 수 있기 때문에, 아무도 메일 앱으로 가장한 앱을 만들 수 없습니다.
프로그램 식별자(identifier) 또는 전체적인 지정된 요구사항(designated requirement)은 서명자에 의해 명시적으로 지정될 수 있습니다. 일반적으로 서명 소프트웨어는 Info.plist
에서 발견된 프로그램의 이름을 CFBundleIdentifier
로 사용하고, 코드 서명을 보호하는 서명 체인을 사용하여 지정된 요구 사항(designated requirement)을 자동으로 작성합니다.
코드 요구사항은 실제로 스크립트로서 명시됩니다. 코드 요구 사항 스크립팅 언어에 대한 자세한 설명은 Code Signing Requirement Language 를 참조하세요.
자자.. 많은 부분을 가져오긴 했지만 더 자세한 내용은 Understanding the Code Signature 를 참고하기로 합시다.
Mach-O
파일에서는 실제로 CodeSignature
구조체를 통해 코드 서명과 관련된 부분을 살펴볼 수 있는데요, 이 CodeSignature
구조체에서는 CodeDirectory
항목을 찾을 수 있습니다.
CodeDirectory
는 코드 서명의 중심이 되는 개념으로, 서명된 코드에 대한 모든 정보를 저장하는 데이터 구조입니다. 이곳에는 특정 파일과 실행 바이너리 파일 조각들의 해시 값들이 담겨져 있습니다. (참고 - iOS 코드 서명에 대해서)
그리고 최종 코드 서명은 CMS(Cryptographic Message Syntax)를 사용하여 이 CodeDirectory
및 기타 속성을 서명합니다. (참고 - TN3126: Inside Code Signing: Hashes)
CodeSignature
의 BlobWrapper
구조체에 방금 설명한 CodeDirectory
를 서명한 데이터와 데이터를 서명한 인증서를 포함하고 있습니다.
더 자세한 내용은 CodeDirectory
와 BlobWrapper
키워드로 구글링을 하시면 reverse engineering 을 통해 알아낸 흥미로운 내용들을 살펴볼 수 있을 듯 한데요, 관련해서 제가 참고했던 레퍼런스들을 몇개 남겨두고 가겠습니다
- Understanding the Code Signature
- iOS 코드 서명에 대해서
- Demystifying iOS Code Signature
- LC_CODE_SIGNATURE
- TN3126: Inside Code Signing: Hashes
- TN3125: Inside Code Signing: Provisioning Profiles
- Inside Code Signing
- What is a provisioning profile & code signing in iOS?
Provisioning Profile
이제 키체인에 있는 서명 인증서로 이 앱을 서명하면 믿을 수 있는 앱이 되니까.. 사용자의 디바이스에서 실행시킬 수 있을까요??
현실은,,, 어림도 없습니다.
기본적으로 Apple 인증서로 서명되어 App Store 에 올라간 앱만이 iOS 기기에서 실행될 수 있습니다.
그렇다면 Apple의 인증서가 아닌, Apple이 발급한 인증서로 서명한 앱을 기기에서 실행하려면 어떻게 해야할까요?? (참고 — iOS 코드 서명에 대해서)
이 앱을 빌드할 때 미리 (참고 — TN3125: Inside Code Signing: Provisioning Profiles)
- 해당 앱은 어느 디바이스 에서 실행할 수 있는지?
- 해당 앱은 언제 실행할 수 있는지?
- 앱의 권한은 어떤 것들이 있는지?
등의 온갖 제약 조건을 명시해둔 다음에, 실제 디바이스에서 앱을 실행할 때의 환경이 이 제약 조건과 일치하면 “음.. 이 정도면 실행시킬만 하지!” 라고 생각할 수 있을 것 같습니다.
이런 온갖 제약 조건, 즉 디바이스 내에서 앱을 실행하기 위한 규칙을 모아놓은 것이 바로 “프로비저닝 프로파일” 입니다.
프로비저닝 프로파일 안에 앱 실행에 필요한 App ID 라든지, Entitlement, Certificate, Device ID 정보들을 담아두고, 실제로 구동되는 디바이스 환경이 이 조건에 부합하면 그제서야 앱 실행을 허용합니다.
즉, 프로비저닝 프로파일은 특정 기기에서 특정 앱을 실행할 수 있는지 확인하는 데 필요한 정보의 컨테이너라고 생각할 수 있습니다. (참고 — Inside Code Signing)
실제로 앱이 디바이스에서 실행되기 위해서는 대표적으로,
앱의 번들 ID가 profile 에 명시된 앱 ID와 일치하고,
앱에서 요청하는 모든 Entitlements 는 profile 의 entitlements 에 포함되어야하며 (참고 — TN3125: Inside Code Signing: Provisioning Profiles)
앱에 서명한 인증서가 프로파일의 인증서 목록에 포함 되어있어야합니다.
프로비저닝 프로파일의 DeveloperCertificates 는 이 프로비저닝 프로파일을 사용하는 앱에 서명할 수 있는 모든 인증서 목록입니다. 이 목록에 없는 인증서로 앱에 서명하면, 서명에 사용된 인증서가 유효한지 여부에 관계없이 앱이 실행되지 않습니다. (참고 — Inside Code Signing)
마지막으로 디바이스가 프로파일의 디바이스 목록에 있어야합니다 (참고 — Distribution methods)
이런 비교 과정을 거친 후에야 비로소 온전히 앱을 실행할 수 있습니다.
프로비저닝 프로파일 직접 만들기 위해서는 애플 개발자 페이지에서 사용할 provisioning profile 종류를 선택하고 (여기서는 우선 Development 로 설정해보겠습니다),
App ID 와
아까 만든 Certificate 와
이 앱을 설치할 수 있는 기기들을 선택한 후에
생성 및 다운로드 하면
이렇게 mobile provision 이라는 파일을 얻을 수 있는데요
다운받은 프로파일은 엑스코드의 Signing & Capabilities 탭에서 설정하면 됩니다.
그럼 최종적으로 빌드된 앱 번들에 embedded.mobileprovision
이라는 이름으로 포함됩니다.
이 embedded.mobileprovision
을 살펴보면 실제로 아까 말한 앱 아이디, 1년의 유효 기간, 푸시 알림 등과 같이 앱에서 사용할 수있는 Entitlements (권한/자격), Certificate, 앱 실행이 허용 된 기기의 UDID 목록 등이 명시되어 있습니다.
사실 최근 시스템에서는 프로파일의 기존 property list 대신,
프로파일의 binary 형식을 갖는 DER-Encoded-Profile
property 가 새로운 source of truth 의 역할을 합니다 (참고 - TN3125: Inside Code Signing: Provisioning Profiles)
그런데 “🤔 방금 다운 받은 Provisioning Profile만 엑스코드에서 설정하고, code signing 에 이용할 키체인의 서명 인증서는 따로 설정 안한것 같은데??” 라는 의문이 들 수 있습니다.
이것이 가능한 이유는 Xcode가 선택된 프로비저닝 프로파일에서 인증서를 추론하려고 시도하기 때문입니다. 프로비저닝 프로파일에 인증서가 포함되어 있기 때문에 이를 수행할 수 있습니다. (참고 — 4. Code Signing & Provisioning, What is a provisioning profile & code signing in iOS?)
지금까지의 과정을 살펴보면
5. 엑스코드에서 프로파일 만들게 해서
6. 특정 경로에 다운받고
7. 앱 빌드할때 같이 넣어서
8. 번들에 포함시킵니다
배포용 Certificate 와 Provisioning Profile
이제 배포를 위한 인증서와 프로파일의 내용으로 넘어가보겠습니다. 앞의 내용을 이해하고 나면, 이 내용들은 비교적 간단합니다.
지금까지 예로 든건, Development 용도의 Certificate 와 Provisioning Profile 에 대한 내용이었습니다.
하지만 저희가 매번 기기에서 앱을 실행하기 위해서, 컴퓨터에 기기를 연결하고 Xcode 에서 실행시킬 순 없잖아요?
내부 Testing 을 위해 앱을 배포하거나 App Store 에 앱을 올려야할텐데, 이를 위해서는 사용해야하는 Distribution 용도의 Certificate 와 Profile 의 종류가 따로 있습니다.
배포용 Certificate
우선 Certificate (인증서) 의 종류는 크게 Development 와 Distribution 으로 나뉘는데요, 방금 살펴본 개발 인증서는 기기에서 앱을 실행하고 앱 기능을 사용할 때 사용하며, 배포 인증서는 테스트를 위해 앱을 배포하거나 App Store Connect 에 업로드할 때 사용합니다 (참고 — 인증서 개요)
그러니까 앱 배포를 위해서는 배포 인증서(Distribution Certificate) 로 사이닝을 해야겠죠?
기존에 사용되었던 앱의 Development 인증서 서명을 제거하고, 다른 서명 인증서를 사용하여 앱을 재서명할 수 있습니다. 엑스 코드에서도 “Re-sign” 이라고 되어있는 것을 확인할 수 있습니다.
이렇게 앱은 배포 인증서로 재서명되며, 인증서가 어떤 이유로든 손상되거나 취소되는 경우, 해당 인증서를 사용하여 배포한 모든 앱안 즉시 작동을 중지하기 때문에 다시 서명하고 다시 배포해야 합니다. 또한 인증서는 3년마다 만료되기 때문에 인증서 수명 주기를 관리하고, 필요시 그에 맞는 앱의 릴리스를 계획해야 합니다. (참고 — App Distribution — From Ad-hoc to Enterprise)
추가로 앱 스토어에 앱을 제출하면 앱 스토어가 배포 프로세스의 일부로 앱에 다시 서명합니다. 즉, 애플은 앱스토어에서 판매되는 모든 앱에 재서명합니다. (참고 — What is app signing?, TN3125: Inside Code Signing: Provisioning Profiles)
배포용 Provisioning Profile
Provisioning Profile 의 종류도 Certificate 와 비슷하게 Development 와 Distribution 을 위해 사용되는 것으로 나뉩니다.
애플 개발자 사이트에서도 실제로 Development 와 Distribution 으로 나뉘어져있는 것을 확인할 수 있습니다.
다만 Distribution 에서 사용되는 Profile 의 종류가 크게 Ad hoc, In-House, App Store 정도로 더 세분화 되는데요,
Xcode 에서 선택한 배포 방법에 맞는 profile 을 사용해야겠죠?
배포 방법에서 App Store Connect 는 익숙하실테니, Ad Hoc 과 Enterprise 를 잠깐 짚고 넘어가겠습니다.
배포 방법 — Ad Hoc
Ad Hoc 의 뜻은 우선 라틴어로, 직역하면 이것에 대해서 (To This) 라는 뜻을 갖고 있습니다.
에?? 라틴어요?? 아니 이름을 누가 이렇게 지어 놓냐고요 ㅜ 새내기때 패기로 들었던 라틴어 교재를 주섬주섬 꺼내오니까 진짜로 있네여..
Ad Hoc 은 개발자 웹 사이트에서 등록된 디바이스에 한해 직접 앱을 설치할 수 있게합니다. 단, 등록 가능한 디바이스의 수는 연간 100대입니다. (참고 — App Distribution — From Ad-hoc to Enterprise)
실제로 Ad Hoc 에 대한 provisioning profile 안을 살펴보면 ProvisionedDevices
쪽에 설치 가능한 디바이스 목록이 명시되어있습니다.
Ad Hoc 은 테스트 목적으로 등록된 기기에 배포할 수 있도록 설계되었습니다. 따라서 규모가 더 큰 팀의 경우 장치 제한에 유의하는 것이 매우 중요합니다. 기기가 부족하면 신제품 개발이 어려울 수 있어 테스터용 개발기기를 사용할 때 주의해야 합니다. 이러한 장치 제한은 1년에 한 번 재설정되며, 계정에 대한 장치 수가 언제 재설정되는지 궁금하다면 개발자 웹 사이트의 회원 페이지로 이동하여 재설정 날짜를 확인할 수 있습니다.
앱을 테스트하려는 사람들의 수가 증가함에 따라 Ad Hoc 이 확장되지 않는다는 것을 금방 깨닫게 됩니다.
배포 방법 — Enterprise
다음으로, 기업 회원은 Enterprise 배포를 선택할 수 있는데요, (참고 — Distribution methods)
이때 사용되는 Provisioning Profile 종류가 In House 입니다. Enterprise 계정에서 Provisioning Profile 을 생성할때 In House 에 대한 옵션을 선택할 수 있습니다.
참고로 In-House 는 ‘회사 조직 내부의’ 라는 뜻입니다.
해당 옵션으로 배포된 앱은 실행 가능한 기기를 지정해 놓지 않기 때문에, In-House 를 사용하여 배포하는 앱은 반드시 직원들에게만 전달되어야 합니다. (참고 — App Distribution — From Ad-hoc to Enterprise)
실제로 Enterprise 로 배포된 앱의 Provisioning Profile 을 보면 Provisioned Devices 목록이 보이지 않습니다. 대신 ProvisionsAllDevices
의 값이 true
로 설정이 되어있습니다.
만약 배포 방법에 따라 provisioning profile 안의 내용이 어떻게 달라지냐! 가 좀 더 궁금시다면 [iOS] Provisioning profile이란 & ipa에서 까보기를 참고해주세여
참고로 프로비저닝 프로파일에 관한 흥미로운 엣지 케이스가 하나 있습니다.
아까 앱 스토어에 앱을 제출하면 앱 스토어가 배포 프로세스의 일부로 앱에 다시 서명한다고 말했잖아여??
사실 애플은 그 전에, 앱이 개발자에 의해 제대로 서명되고 프로비저닝 되었는지부터 확인합니다. 이 검사를 마치고 나면, 이후에는 추가적인 보안 검사를 수행할 필요가 없으므로 앱 스토어에 올라가는 최종 앱에는 프로비저닝 프로파일이 없습니다 (참고 — TN3125: Inside Code Signing: Provisioning Profiles).
Summary
그럼 지금까지 살펴본 내용을 요약해보겠습니다.
사실 애플은 앱 개발과 앱 배포 모두에 자동 코드 서명을 사용할 것을 권장하기 때문에, 대부분 Automatically manage signing 을 잘 체크하고 사용해왔을텐데요 (참고 — Setting up Xcode to automatically manage your provisioning profiles)
사실 이 뒤에서 Xcode 는 아래와 같은 일을 대신 수행해왔습니다. (참고 — automatic signing)
하나씩 살펴볼까여?
- 엑스코드에서 먼저 “키체인아 코드 서명에 필요한 서명 인증서 좀 만들어와라” 라고 하면
- 키체인에서는 “ㅇㅋㅇㅋ 개인키 공개키 키 쌍 만들었구, 공개키 포함해서 CSR 만들어야징~”
- “그리고 애플아, 요청서 가져왔으니까 확인하구 인증서 좀 발급해주라!” 라고 합니다
- 그렇게 다운 받은 인증서는 키체인에서 개인 키와 쌍을 지어 서명 인증서를 형성하게 됩니다.
그 다음
5. 엑스코드에서 다시, “애플아~ 온갖 정보들 다 포함해가지고 Provisioning Profile 좀 만들어주라~” 라고 하면
6. 만들어진 profile 은 특정 경로 (~/Library/MobileDevice/Provisioning Profiles) 에 다운 받아집니다
그 다음
7. 이제 엑스코드에서 “앱 빌드 좀 해볼까나~” 할때
8. 앱 번들에 아까 만든 프로비저닝 프로파일 포함시키고
9. 알맞은 서명 인증서로 서명을 한 후
10. 앱을 실행시킵니다
이제 조금은 감이 잡히실까요?
One More Thing…
마지막으로 한가지 더 클라우드 사이닝에 대해 살짝 알아보겠습니다. (참고 — Distribute apps in Xcode with cloud signing)
앞서 설명했듯 원래는 배포 워크플로우에서 서명할 때, 배포 인증서와 개인 키가 로컬 시스템에 설치되어 있는지 확인하고 수동으로 설정해야 하는 경우가 많았습니다.
하지만 Xcode13 이후 버전에서는 자동 서명을 사용하면 로컬에서 인증서 설정이 필요하지 않습니다. 만약 배포 워크 플로우에서 로컬 서명 인증서를 찾을 수 없는 경우, 클라우드에 저장된 인증서와 개인 키를 사용해서 배포할 모든 앱에 클라우드 서명합니다. (참고 — 클라우드 관리 인증서)
이 새로운 스타일의 서명은 앱스토어 업로드, 엔터프라이즈 배포 등 Xcode의 모든 배포 방식에 지원됩니다.
더 자세한 내용은 Distribute apps in Xcode with cloud signing 영상을 참고해주세요.
마무리
이렇게 Certificate 와 Provisioning Profile 에 대해 정리해봤는데요! Automatically manage signing 뒤에 가려져서 무심코 지나갈 수 있었던 개념과 동작들을 이해하는데 도움이 되었으면 좋겠습니다.
오늘이 일요일인데 내일도 모레도 빨간날이라니 행복해서 눈물만 흘리는 중.. 과연 이번 연휴에는 계획한 일들을 얼마나 할 수 있을까요..? 🤔
뭐 어떻게든 되겠져?! 그럼 20000!!
References
Apple Document
- What is app signing?
- About Code Signing
- Understanding the Code Signature
- TN3126: Inside Code Signing: Hashes
- TN3125: Inside Code Signing: Provisioning Profiles
- Apple 기기에 대한 인증서 관리 개요
- Code Signing
- What’s a certificate?
- Distribution methods
- Certificates
- 개발 Provisioning profile(권한 설정 프로파일) 생성하기
- Ad Hoc Provisioning profile(Ad Hoc 권한 설정 프로파일) 생성하기(iOS, tvOS, watchOS)
- 인증서 개요
- 인증서 유형
- automatic signing
- Distribution overview
- Create, export, and delete signing certificates
- Manually manage distribution signing
- 클라우드 관리 인증서
- Setting up Xcode to automatically manage your provisioning profiles
- Using the latest code signature format
WWDC
Kodeco
Medium
- Demystifying iOS Code Signature
- What is a provisioning profile & code signing in iOS?
- iOS Code Signing breakdown
- iOS Code Signing & Provisioning in a Nutshell
Line
유투브
- TechTalk | iOS 앱 서명 개요
- # 3 : iOS의 경우 Fastlane | Cert 및 Sigh
- What is code signing and how does it work?
기타
- A Deep Dive into iOS Code Signing
- LC_CODE_SIGNATURE
- Inside Code Signing
- iOS Code Signing, Development and Distribution Provisioning Profiles explained
- 코드 서명이란 무엇인가요?
- 코드 서명이란 무엇입니까? 이 보안 코딩 프로세스에 대한 심층 분석
- 코드 서명 인증서는 어떻게 작동합니까?
- [gym] Use Xcode 13’s cloud signing
- CSR(Certificate Signing Request)이란?
- [용어] PKI(비대칭키, 공개키 기반구조)에 대한 메모, PKCS#x, Cms, Hash, RSA, 등….