iOS Provisioning Profile(Certificate)与Code Signing详解 - Go语言中文社区

iOS Provisioning Profile(Certificate)与Code Signing详解


引言

        关于开发证书配置(Certificates & Identifiers & Provisioning Profiles),相信做 iOS 开发的同学没少被折腾。对于一个 iOS 开发小白、半吊子(比如像我自己)抑或老兵,或多或少会有或曾有过以下不详、疑问、疑惑甚至困惑:

  1. 什么是App ID?Explicit/Wildcard App ID有何区别?什么是App Group ID?
  2. 什么是证书(Certificate)?如何申请?有啥用?
  3. 什么是Key Pair(公钥/私钥)?有啥用?与证书有何关联?
  4. 什么是签名(Signature)?如何签名(CodeSign)?怎样校验(Verify)?
  5. 什么是(Team)Provisioning Profiles?有啥用?
  6. Xcode如何配置才能使用iOS真机进行开发调试?
  7. 多台机器如何共享开发者账号或证书?
  8. 遇到证书配置问题怎么办?
  9. Xcode 7免证书调试真机调试

本文将围绕相关概念及背景做个系统的梳理串烧,于条分缕析中对证书体系进行抽丝剥茧,逐步揭开签名机制的神秘面纱。图穷匕首见,水落而石出,包教不包会,不会请再来。

从 Xcode 7 开始支持普通 Apple 账号进行免证书真机调试,详情参考最新官方文档《Launching Your App on Devices》,或参考本文最后一节简介。

写在前面

1.假设你使用过 Apple 设备(iMac/iPad/iPhone)且注册过 Apple ID(Apple Account),详情参考《创建和开始使用 Apple ID》。

2.假设你或你所在的开发组已加入苹果开发者计划(Enroll in iOS Developer Program to become a member),即已注册开发者账号(Apple Developer Account)。

  • 只有拥有开发者账号,才可以申请开发/发布证书及相关配置授权文件,进而在 iOS 真机上开发调试 Apps 或发布到 App Store。
  • 开发者账号分为 Individual 和 Company/Organization 两种类型。如无特别交代,下文基于 $99/Year 的普通个人开发者(Individual)账号展开

3.若要真机调试实践,你必须至少拥有一台装有 macOS/Xcode 的 Mac 开发机(iMac or MacBook),其上自带原生的 Keychain Access。

.App ID(bundle identifier)

在苹果官方的开发者计划(Apple Developer Member Center层面,App ID 即 Product ID,用于标识一个或者一组 App。

在 Mac/iOS 开发语境中,bundle捆绑) 是指一个内部结构按照标准规则组织的特殊目录。在 Mac OS 应用程序目录下的某个 *.app 上可右键显示包内容(Contents),其本质上就是可执行二进制文件(MacOS/)及其资源(Resources/)的打包组合

App ID 字符串通常以反域名(reverse-domain-name)格式的 Company Identifier(Company ID)作为前缀(Prefix/Seed),一般不超过 255 个 ASCII 字符。

App ID 全名会被追加 Application Identifier Prefix(一般为 TeamID.),分为两类:

  • Explicit App ID:唯一的 App ID,用于唯一标识一个应用程序。例如“com.apple.garageband”这个 App ID,用于标识 Bundle Identifier 为“com.apple.garageband”的 App——GarageBand;com.tencent.mqq”则为iPhoneQQ 的 App ID
  • Wildcard App ID:含有通配符的 App ID,用于标识一组应用程序。例如“*”(实际上是 Application Identifier Prefix)表示所有应用程序;而“com.apple.*”可以表示 Bundle Identifier 以“com.apple.”开头(苹果公司)的所有应用程序。
用户可在 Developer Member Center 网站上注册(Register)或删除(Delete)已注册的 App IDs。
在 Xcode 中 配置到XcodeTarget|Info|Bundle Identifier】中的 Bundle Identifier 必须和 App ID 是一致(Explicit)或匹配(Wildcard)。对于 Wildcard App ID,只要 bundle identifier 包含其作为 Prefix/Seed 即可。

.设备(Device)

Device 就是运行 iOS 系统用于开发调试 App 的设备。每台 Apple 设备使用 UDID (Unique Device Identifier)唯一标识。

iOS 设备连接 Mac 后,可通过 iTunes->Summary 或者 Xcode->Window->Devices 查看其 UDID

Apple Member Center 网站个人账号下的 Devices 中包含了注册过的所有可用于开发和测试的设备,普通个人开发账号每年累计最多只能注册100个设备。

  • Apps signed by you or your team run only on designated development devices.
  • Apps run only on the test devices you specify.
用户可在网站上注册或启用/禁用(Enable/Disable)已注册的 Device。
本文的 Devices 是指连接到 macOS/Xcode 被授权用于开发测试的 iOS 设备(iPhone/iPad)。

.开发证书(Certificates)

1.证书的概念

证书是由公证处或认证机关开具的证明资格或权力的证件,它是表明(或帮助断定)事理的一个凭证。证件或凭证的尾部通常会烙印公章

每个中国人一生可能需要70多个证件,含15种身份证明。证件中“必需的”有30到40个。将这些证件按时间顺序铺开,那就是一个天朝子民的一生——持准生证许可落地,以户籍证明入籍,以身份证认证身份,持结婚证以合法同居,最终以死亡证明注销。

2.数字证书的概念

数字证书就是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在 Internet 上验证通信实体身份的方式,其作用类似于日常生活中的身份证或司机的驾驶执照。

注意:本文讨论的数字证书是基于 X.509 公共密钥体系(PKI,Public key infrastructure)的公钥证书(Public key certificate

数字证书是由权威的CA机构Certificate authority数字证书认证机构或数字证书授权中心颁发发行)的,人们可以在网上用它来识别对方的身份。


  • 数字证书是一个经 CA 数字签名的包含公开密钥拥有者信息以及公开密钥的文件。最简单的证书包含一个公开密钥、名称以及 CA 的数字签名。
  • 数字证书还有一个重要的特征就是时效性:只在特定的时间段内有效。
关于数字证书的构成要素,参考 X.509 § Structure of a certificate

数字证书中的公开密钥(公钥)相当于公章

3.根证书的概念

证书的信任链条(Chain of trust)是环环相扣的,根证书(Root certificate)就是一开始就被信任的证书,是信任源(trust anchor),即信任链的起点

根证书是被严格限制和确认的,根证书的颁发者被称之为 Root Certificate Authority(Root CA)某一认证领域内的根证书是 CA 认证中心自行签名给自己颁发的证书(Self-signed certificate),安装根证书意味着对这个 CA 认证中心的信任。

> 在天朝子民的一生中,户籍证明为证源(根证书,Root certificate);有了户籍证明,才能办理身份证(中间证书,Intermediate certificate);有了上流的身份证,才能办理下游特定领域(End-entity)所需的居住证、结婚证、计划生育证、驾驶执照等认证(叶子证书,leaf certificate)。

这里首当其冲需要解决的问题是:由谁来保证根证书作为信任链起点的安全?

现代网络操作系统都会内置一份可信的根证书列表(Firefox 的根证书列表独立于操作系统之外):操作系统发行厂商通过严格地审核,将安全可靠、可被信任的第三方机构(TTP,trusted third party)纳入白名单,并将这些权威可信 CA 的根证书 预装内置 到系统中。

》在 Windows Internet Explorer 中,通过菜单【工具 | Internet 选项 | 内容 | 证书】可以查看受信任的根证书颁发机构(或中间证书颁发机构):

》在 macOS Keychain Access 中,可查看系统根证书(或系统证书):


常见的权威 CA 根证书有

  • AddTrust External CA Root(The USERTrust Network™)
  • Baltimore CyberTrust Root(DigiCert Baltimore Root)
  • DigiCert Global Root CA(DigiCert)
  • DigiCert High Assurance EV Root CA(DigiCert)
  • DST Root CA X3
  • GeoTrust Global CA
  • GeoTrust Primary Certification Authority
  • GlobalSign(颁发者:GlobalSign Root CA - R3;签名算法:sha256RSA——带 RSA 加密的 SHA-256)
  • GlobalSign(颁发者:GlobalSign Root CA - R2;签名算法:sha1RSA——带 RSA 加密的 SHA-1)
  • GlobalSign Root CA(组织:GlobalSign nv-sa)
  • Go Daddy Class 2 Certification Authority(组织:The Go Daddy Group, Inc.)
  • Go Daddy Root Certificate Authority - G2(组织:GoDaddy.com, Inc.)
  • QuoVadis Root Certification Authority(组织:QuoVadis Limited)
  • Starfield Class 2 Certification Authority
  • Starfield Services Root Certificate Authority( - G2)(组织:Starfield Technologies, Inc.)
  • StartCom Certification Authority(签名算法:sha1RSA——带 RSA 加密的 SHA-1)
  • thawte Primary Root CA
  • thawte Primary Root CA - G3
  • UTN-USERFirst-Object(组织:The USERTRUST Network)
  • VeriSign Universal Root Certification Authority(组织单位:VeriSign Trust Network)
  • VeriSign Class 3 Public Primary Certification Authority - G5(组织单位:VeriSign Trust Network)

--------------------------------------------------------------------------------
Windows 下微软颁发的证书
--------------------------------------------------------------------------------

  • Microsoft Root Authority
  • Microsoft Root Certificate Authority
  • Symantec Enterprise Mobile Root for Microsoft

--------------------------------------------------------------------------------
macOS 下苹果颁发的证书
--------------------------------------------------------------------------------
  • Apple Root CA
  • Apple Root Certificate Authority
  •     Developer ID Certification Authority(系统根证书)
  •     Apple Worldwide Developer Relations Certification Authority(系统证书)
椭圆曲线公共密钥
  1. 签名算法:带 SHA-256 的 ECDSA 签名;公共密钥算法:椭圆曲线公共密钥;参数为[椭圆曲线 secp256r1]
  2. 签名算法:带 SHA-384 的 ECDSA 签名;公共密钥算法:椭圆曲线公共密钥;参数为[椭圆曲线 secp384r1]
macOS 预装了 Apple Root CA、GlobalSign、GeoTrust、Symantec、thawte、VeriSign 等权威机构的包含椭圆曲线公共密钥的根证书:
  • GlobalSign(组织单位:GlobalSign ECC Root CA - R4;带 SHA-256 的 ECDSA 签名)
  • GlobalSign(组织单位:GlobalSign ECC Root CA - R5;带 SHA-384 的 ECDSA 签名)
  • Apple Root CA - G3(组织单位:Apple Certification Authority;带 SHA-384 的 ECDSA 签名)
  • GeoTrust Primary Certification Authority - G2(组织:GeoTrust Inc.;带 SHA-384 的 ECDSA 签名)
  • Symantec Class 1/2/3 Public Primary Certification Authority - G4(组织单位:Symantec Trust Network;带 SHA-384 的 ECDSA 签名)
  • thawte Primary Root CA - G2(组织:thawte, Inc.;带 SHA-384 的 ECDSA 签名)
  • VeriSign Class 3 Public Primary Certification Authority - G4(组织单位:VeriSign Trust Network;带 SHA-384 的 ECDSA 签名)

为了防止 GFW 进行中间人攻击(MitM),例如篡改 github 证书,导致无法访问 github 网站等问题,可选择不信任 CNNIC

  • 在[钥匙串-系统]中双击 CNNIC ROOT,在【信任】|【使用此证书时】下拉选择【永不信任】。


4.iOS(开发)证书

iOS 证书是用来证明 iOS App 内容(bundle with executable and resources)的合法性和完整性的数字证书。对于想安装到真机或发布到 AppStore 的应用程序(App),只有经过签名验证(Signature Validated)才能确保来源可信,并且保证 App 内容是完整、未经篡改的。

iOS 证书分为两类:Development 和 Production(Distribution)

  • Development 证书用来开发和调试应用程序:A development certificate identifies you, as a team member, in a development provisioning profile that allows apps signed by you to launch on devices. 
  • Production 主要用来分发应用程序(根据证书种类有不同作用):A distribution certificate identifies your team or organization in a distribution provisioning profile and allows you to submit  your app to the store. Only a team agent or an admin can create a distribution certificate.

普通个人开发账号最多可注册 iOS Development/Distribution 证书各2个,用户可在网站上删除(Revoke)已注册的 Certificate。

下文主要针对 iOS App 开发调试过程中的开发证书(Certificate for Development)。

5.iOS(开发)证书的根证书

那么,iOS 开发证书是谁颁发的呢?或者说我们是从哪个 CA 申请到用于 Xcode 开发调试 App 的证书呢?

iOS 以及 Mac OS X 系统(在安装 Xcode 时)将自动安装 AppleWWDRCA.cer 这个中间证书(Intermediate Certificates),它实际上就是 iOS(开发)证书的证书,即开发根证书

AppleWWDRCA.cer 是由苹果公司一级认证中心 Apple Certification Authority(Apple Root CA)给下属的 Apple Worldwide Developer Relations Certification Authority 这个二级证书机构(subordinate CA)颁发的证书。而苹果根证书则是被默认预装到 macOS 系统中的,在 Keychain Access 系统根证书中可以找到 Apple Root CA 为自己颁发的根证书。

Apple Root CA 之于  AppleWWDRCA 好比户籍证之于身份证AppleWWDRCA 之于 iOS(开发)证书则好比身份证之于驾驶证




如果 Mac Keychain Access 证书助理在申请证书时尚未安装过 AppleWWDRCA.cer 证书,请先下载安装(Signing requires that you have both the signing identity and the intermediate certificate installed in your keychain)。

下载到本地后,手动点击 *.cer 安装证书到 macOS 时,Keychain Access 追溯其签发 CA 为 Apple Root CA,利用 Apple Root CA 证书公钥对其数字签名进行解密和校验。校验成功会标记此证书有效(This certificate is valid)。


二级证书路径为:

Apple Root CA
└── Apple Worldwide Developer Relations Certification Authority

6.申请 iOS 开发证书(CSR:Certificate Signing Request)

可以在缺少证书时通过 Xcode Fix Issue 自动请求证书,但是这会掩盖其中的具体流程细节。这里通过 Keychain 证书助理从证书颁发机构请求证书:填写开发账号邮件和常用名称,勾选【存储到磁盘】。


Keychain Access|Keys 中将新增一对非对称密钥对 Public/Private Key Pair(This signing identity consists of a public-private key pair that Apple issues)。同时,keychain 将生成一个包含开发者身份信息公钥CSR(Certificate Signing Request)文件——CertificateSigningRequest.certSigningRequest。


私钥 private key 始终保存在 Mac OS 的 Keychain Access 中,用于签名(CodeSign)本机对外发布的 App公钥 public key 一般随证书(随Provisioning Profile,随 App 安装)散布出去,对 App 签名进行校验认证。用户必须妥善保存本地 Keychain 中的 private key,以防伪冒。

  • Keep a secure backup of your public-private key pair. If the private key is lost, you’ll have to create an entirely new identity to sign code. 
  • Worse, if someone else has your private key, that person may be able to impersonate you.

在 Apple 开发网站上传包含公钥的 CSR 文件作为换取证书的凭证(Upload CSR file to generate your certificate),有点类似为github账号添加SSH公钥到服务器上进行授权。

Apple Developer 开发证书颁发机构 WWDRCA 将使用其 private key 对 CSR 中的 public key 和一些身份信息进行加密签名生成数字证书(ios_development.cer)并记录在案(Apple Member Center)。


从 Apple Member Center 网站下载证书到 Mac 上双击即可安装(当然也可在 Xcode 中添加开发账号自动同步证书和[生成]配置文件)。

手动点击 *.cer 安装证书到 macOS 时,Keychain Access 追溯其签发 CA 为 AppleWWDRCA(Apple Worldwide Developer Relations Certification Authority),利用 AppleWWDRCA 证书公钥对该开发证书数字签名进行解密和校验。校验成功会标记此证书有效(This certificate is valid)。

三级开发证书路径为:

Apple Root CA
└── Apple Worldwide Developer Relations Certification Authority
    └── iPhone Developer: *@gmail.com (**********)

在 Keychain Access 的 Login | My Certificates 可查看到安装成功的证书。



Keychain Access 的 Login | Keys 中展开创建 CSR 时生成的 Key Pair 中的私钥前面的箭头,可以查看到包含其对应公钥的证书(Your requested certificate will be the public half of the key pair.);

在 Keychain Access|Certificates 中展开安装的证书(ios_development.cer)前面的箭头,可以看到其对应的私钥



Certificate 应被配置到Xcode Target|Build Settings|Code Signing|Code Signing Identity】下,下拉选择 Identities from Profile "..."(一般先配置 Provisioning Profile)。以下是 Xcode 配置示例:


.供应配置文件(Provisioning Profiles

1.Provisioning Profile 的概念

Provisioning Profile 文件包含了上述的所有内容:证书、App ID 和 设备 ID


一个 Provisioning Profile 对应一个 Explicit App ID 或 Wildcard App ID(一组相同 Prefix/Seed 的 App IDs)。在网站上手动创建一个 Provisioning Profile 时,需要依次指定 App ID(单选)、证书(Certificates,可多选)和设备(Devices,可多选)。用户可在网站上删除(Delete)已注册的 Provisioning Profiles。

Provisioning Profile 决定 Xcode 用哪个证书(公钥)/私钥组合(Key Pair/Signing Identity)来签署应用程序(Signing Product),并将在应用程序打包时嵌入到 .ipa 包里。安装应用程序时,Provisioning Profile 文件被拷贝到 iOS 设备中,运行该 iOS App 的设备通过它来认证安装的程序。

如果要打包到真机上运行一个APP,一般要经历以下三步:

  • 首先需要指明它的 App ID,并且验证 Bundle ID 是否与其一致;
  • 其次需要证书对应的私钥来进行签名,用于标识这个 APP 是合法、安全、完整的;
  • 然后,如果是真机调试,需要确认这台设备是否授权运行该 APP。

Provisioning Profile 把这些信息全部打包在一起,方便我们在调试和发布程序打包时使用。这样,只要在不同的情况下选择不同的 Provisioning Profile 文件就可以了。

Provisioning Profile 也分为 Development 和 Distribution 两类,有效期同 Certificate 一样。Distribution 版本的 ProvisioningProfile 主要用于提交 App Store 审核,其中不指定开发测试的Devices(0,unlimited)。App ID 为 Wildcard App ID(*)。App Store 审核通过上架后,允许所有 iOS 设备(Deployment Target)上安装运行该App。

Xcode 将全部供应配置文件(包括用户手动下载安装的和 Xcode 自动创建的 Team Provisioning Profile)放在目录 ~/Library/MobileDevice/Provisioning Profiles 下。

2.Provisioning Profile的构成

以下为典型供应配置文件 *.mobileprovision 的构成简析

1)Name:该mobileprovision的文件名。

2)UUID:该mobileprovision文件的真实文件名。

3)TeamNameApple ID账号名。

4)TeamIdentifierTeam Identity。

5)AppIDNameexplicit/wildcard App ID name(ApplicationIdentifierPrefix)。

6)ApplicationIdentifierPrefix:完整App ID的前缀(TeamIdentifier.*)。

7)DeveloperCertificates:包含了可以为使用该配置文件应用签名的所有证书<data><array>。

证书是基于 Base64 编码,符合 PEM(PrivacyEnhanced Mail, RFC 1848) 格式的,可使用 OpenSSL 来处理(opensslx509 -text -in file.pem)。

从 DeveloperCertificates 提取 <data></data> 之间的内容到文件 cert.cer(cert.perm):

-----BEGIN CERTIFICATE-----

<data></data>之间的内容拷贝至此

-----END CERTIFICATE-----`

Mac 下右键 QuickLook 查看 cert.cer(cert.perm),在 Keychain Access 中右键 Get Info 查看对应证书 ios_development.cer,正常情况(公私钥 KeyPair 配对)应吻合;Windows 下没有足够信息(WWDRCA.cer),无法验证该证书。

如果你用了一个不在这个列表中的证书进行签名,无论这个证书是否有效,这个应用都将 CodeSign Fail。

8)Entitlements <key>对应的<dict>:

keychain-access-groups$(AppIdentifierPrefix),参见Code Signing Entitlements(*.entitlements)。

每个应用程序都有一个可以用于安全保存一些如密码、认证等信息的 keychain,一般而言自己的程序只能访问自己的 keychain。通过对应用签名时的一些设置,还可以利用keychain的方式实现同一开发者签证(就是相同bundle seed)下的不同应用之间共享信息的操作。比如你有一个开发者帐户,并开发了两个不同的应用A和B,然后通过对A和B的 keychain access group 这个东西指定共用的访问分组,就可以实现共享此 keychain 中的内容。

application-identifier:带前缀的全名,例如$(AppIdentifierPrefix)com.apple.garageband。

com.apple.security.application-groupsApp Group ID(group. com.apple),参见Code Signing Entitlements(*.entitlements)。

com.apple.developer.team-identifier:同Team Identifier。

9)ProvisionedDevices:该mobileprovision授权的开发设备的UDID <array>。

Provisioning Profile被配置到XcodeTarget|Build Settings|Code Signing|Provisioning Profile】下,然后在Code Signing Identity下拉可选择Identities from Profile "..."(即

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/phunxm/article/details/42685597
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 22:18:34
  • 阅读 ( 1551 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢