iOS开发证书要点详解

转自 iOS开发证书要点详解,ios证书详解 有细节修改。

首先,假设你使用过Apple设备(iMac/iPad/iPhone)且注册过Apple ID(Apple Account)。

其次,你必须加入苹果开发者计划(Enroll in iOS Developer Program to become a member),注册一个开发者账号。

只有拥有开发者账号,才可以申请开发/发布证书及相关配置授权文件,进而在iOS真机上开发调试Apps或发布到App Store。

开发者账号分为Individual和Company/Organization两种类型。如无特别交代,下文基于$99/Year的普通个人开发者(Individual)账号展开。

一、App ID(bundle identifier)

App ID用于标识一个或者一组App,App ID应该和Xcode中的Bundle Identifier是一致的或匹配的。

App ID字符串通常以反域名(reverse-domain-name)格式的Company Identifier(Company ID)作为前缀(Prefix/Seed)。

App ID全名会被追加ApplicationIdentifierPrefix(一般为TeamID)。

App ID分为两类:

Explicit App ID:唯一的App ID,这种App ID用于唯一标识一个应用程序。例如“com.apple.garageband”这个App ID,用于标识Bundle Identifier为“com.apple.garageband”的程序。

Wildcard App ID:通配符App ID,用于标识一组应用程序。例如 “*”(实际上是ApplicationIdentifierPrefix)表示所有应用程序;而“com.apple.*”可以表示以“com.apple.”开头的所有应用程序。

用户可在网站上删除已注册的App IDs。App ID被配置到Xcode的【Target > Info > Bundle Identifier】下,对于Wildcard App ID,只要bundle identifier包含其作为Prefix/Seed即可。

二、设备(Device)

Device就是运行iOS系统用于开发调试App的设备,每台设备使用UDID来唯一标识。iOS设备连接Mac后,可通过iTunes > Summary(点击序列号可以进行切换内容)或者Xcode > Window > Devices 获取iPhone的UDID(identifier)。

Apple Member Center网站个人账号下的Devices中包含了注册过的所有可用于开发和测试的设备。普通个人开发账号每年累计最多只能注册100个设备,用户可在网站上启用/禁用(Enable/Disable)已注册的Device。

Apps signed by you or your team run only on designated development devices.
Apps run only on the test devices you specify.

本文的Devices即连接到Xcode被授权用于开发测试的iOS设备(iPhone/iPad)。

三、证书(Certificates)

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

证书分为两类: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。下文主要针对开发调试阶段的Development证书。

首先,iOS以及Mac OS X系统(在安装Xcode时)将自动安装AppleWWDRCA.cer(Apple Worldwide Developer Relations Certification Authority)这个中间证书(Intermediate Certificates)。它实际上就是iOS证书的CA(Certificate Authority:证书颁发机构),其公钥用于解密认证证书的可靠性。

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

img

通过Keychain证书助理手动申请(证书助理 > 从证书颁发机构请求)开发证书时(也可通过Xcode自动请求生成),keychain将生成一个包含开发者身份信息的CSR(Certificate Signing Request)文件。

同时,Keychain Access > Keys (种类/密钥)中将新增一对Public / Private Key Pair(This signing identity consists of a public-private key pair that Apple issues)。

img

private key用于签名(CodeSign),始终保存在Mac OS的Keychain Access中;public key一般随证书散布出去,对签名进行校验认证。用户必须保护好本地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文件,Apple证书颁发机构WWDRCA将使用private key对CSR中的public key和一些身份信息进行加密签名生成数字证书(ios_development.cer)并记录在案(Apple Member Center)。

从Apple Member Center网站下载证书到Mac上双击即可安装。证书安装成功后,在KeychainAccess > Keys中展开创建CSR时生成的Key Pair中的私钥前面的箭头,可以查看到包含其对应公钥的证书(Your requested certificate will be the public half of the key pair.),在Keychain Access > Certificates中展开安装的证书(ios_development.cer)前面的箭头,可以看到其对应的私钥。

img
img

Certificate被配置到Xcode【 Target > Build Settings > Code Signing > Code Signing Identity】下,下拉选择Identities from Profile "..."(一般先配置Provisioning Profile)。

四、供应配置文件(Provisioning Profiles)

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

Provisioning Profile决定Xcode用哪个证书(公钥)/私钥组合(Key Pair/Signing Identity)来签署应用程序(Signing Product),将在应用程序打包时嵌入到.ipa包里。

安装应用程序时,Provisioning Profile文件被拷贝到iOS设备中,运行该iOS App的设备也通过它来认证安装的程序。如果要打包或者在真机上运行一个APP,一般要经历以下三步:

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

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

(1)Name:该mobileprovision的文件名。

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

(3)TeamName:Apple ID账号名。

(4)TeamIdentifier:Team Identity。

(5)AppIDName:explicit/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-groups:App Group ID(group. com.apple),参见Code Signing Entitlements(*.entitlements)。

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

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

Provisioning Profile被配置到Xcode【Target > Build Settings > Code Signing > Provisioning Profile】下,然后在Code Signing Identity下拉可选择Identities in keychain "..."(即Provisioning Profile中包含的Certificates)或者选择Automatic, Xcode自动选择。

五、开发组供应配置文件(未实际操作过)

(Team Provisioning Profiles每个Apple开发者账号都对应一个唯一的Team ID,Xcode3.2.3预发布版本中加入了Team Provisioning Profile这项新功能。在Xcode中添加Apple Developer Account时,它将与Apple Member Center后台勾兑自动生成iOS Team Provisioning Profile(Managed by Xcode)。

img

Team Provisioning Profile包含一个为Xcode iOS Wildcard App ID()生成的iOS Team Provisioning Profile:*(匹配所有应用程序),账户里所有的Development Certificates和Devices都可以使用它在这个eam注册的所有设备上调试所有的应用程序(不管bundleidentifier是什么)。同时,它还会为开发者自己创建的Wildcard/Explicit App IDs创建对应的iOSTeam Provisioning Profile。

Team Provisioning Profile生成/更新时机:
Add an Apple ID account to Xcode
Fix issue "No Provisioning Profiles with a valid signing identity" in Xcode
Assign Your App to a Team in Xcode project settings of General / Identity
Register new device on the apple development website or Xcode detected new device connected

利用Xcode生成和管理的iOS Team Provisioning Profile来进行开发非常方便,可以不需要上网站手动生成下载Provisioning Profile。
Team Provisioning Profile同Provisioning Profile,只不过是由Xcode自动生成的,也被配置到Xcode【Target > Build Settings > Code Signing > Provisioning > Profile】下。

六、App Group (ID)(未实际操作过)

WWDC14除了发布了OS X v10.10和switf外,iOS 8.0也开始变得更加开放了。

说到开放,当然要数应用扩展(App Extension)了。顾名思义,应用扩展允许开发者扩展应用的自定义功能和内容,能够让用户在使用其他应用程序时使用该项功能,从而实现各个应用程序间的功能和资源共享。可以将扩展理解为一个轻量级(nimble and lightweight)的分身。扩展和其Containing App各自拥有自己的沙盒,虽然扩展以插件形式内嵌在Containing App中,但是它们是独立的二进制包,不可以互访彼此的沙盒。为了实现Containing App与扩展的数据共享,苹果在iOS 8中引入了一个新的概念——App Group,它主要用于同一Group下的APP实现数据共享,具体来说是通过以App Group ID标识的共享资源区——App Group Container。用户可在网站上编辑Explicit App IDs的App Group Assignment;可以删除(Delete)已注册的AppGroup (ID)。Containing App与Extension的Explicit App ID必须Assign到同一App Group下才能实现数据共享,并且Containing App与Extension的App ID命名必须符合规范:假如Garageband这个App ID为“com.apple.garageband”,则支持从语音备忘录导入到Garageband应用的插件的App ID可能形如“com.apple.garageband.extImportRecording”。

img

关于Provisioning Profile,可以使用自己手动生成的,也可以使用Xcode自动生成的Team Provisioning Profile。
App Group会被配置到Xcode【 Target > Build Settings > Code Signing > Code Signing Entitlements】文件(*.entitlements)的键com.apple.security.application-groups下,不影响Provisioning Profile生成流程。

七、证书与签名(Certificate& Signature)

img

每个证书(其实是公钥)对应的私钥会被用来对内容(executable code,resources such as images and nib files aren’t signed)进行数字签名(CodeSign)——使用哈希算法生成内容摘要(digest)。上面已经提到,公钥被包含在数字证书里,数字证书又被包含在描述文件(Provisioning File)中,描述文件在应用被安装的时候会被拷贝到iOS设备中。
iOS/Mac机上的ios_development.cer可以被AppleWWDRCA.cer中的 public key解密,从而获取每个开发证书中可信任的公钥。
1.iOS/Mac设备(系统)使用CA证书(WWDRCA.cer)来判断App Provisioning Profile(Code Signing Identity)的合法性:
若用WWDRCA公钥能成功解密出证书并得到公钥(Public Key)和内容摘要(Signature),证明此证书确乃AppleWWDRCA发布,即证书来源可信;
再对证书本身使用哈希算法计算摘要,若与上一步得到的摘要一致,则证明此证书未被篡改过,即证书完整。

2.iOS/Mac设备(系统)使用AppProvisioning Profile(Code Signing Identity)证书来判断App的合法性:
若用证书公钥能成功解密出App(executable code)的内容摘要(Signature),证明此App确乃认证开发者发布,即来源可信;
再对App(executable code)本身使用哈希算法计算摘要,若与上一步得到的摘要一致,则证明此App(executable code)未被篡改过,即内容完整。

证书签名详细问题可以见另一篇文章:iOS签名的原理

八、在多台机器上实现开发账户/证书共享

在安装过的开发机上的keychain Access 中导出对应的证书为p12文件传到别的机器。

其他Mac机器上双击Certificates.p12(如有密码需输入密码)即可安装该共享证书,在开发者网站上将欲调试的iOS设备注册到该开发者账号名下,并下载对应证书授权了iOS调试设备的Provisioning Profile文件即可在iOS真机设备上开发调试。

九、证书配置常见错误和其他

1、Xcode Target > Genera > Identity Team下提示"Your build settings specify a provisioning profile with the UUID "xxx",howerver, no such provisioning profile was found."

解:Xcode Target > BuildSettings > Code Signing 当前配置的指定UDID的provisioningprofile在本地不存在,此时需要更改Provisioning

2、Build Settings > CodeSigning的Provisioning Profile中选择了本地安装的provisioningprofile之后,Code Signing Identity中下拉提示No identities from profile “…”or No identities from keychain.

解:Xcode配置指定UDID的provisioning profile中的DeveloperCertificates在本地KeyChain中不存在(No identities are available)或不一致(KeyPair中的Private Key丢失),此时需去网站检查ProvisioningProfile中的App ID-Certificate-Device配置是否正确。如果是别人提供的共享账号(.developerprofile)或共享证书(.p12),请确保导出了对应Key Pair中的Private Key。必要时也直接在Xcode中Fix issue予以解决(可能自动生成iOS Team ProvisioningProfile)。

3、"Invalid application-identifier Entitlement"or "Code Signing Entitlements file do not match those specified in your provisioning profile.(0xE8008016)."

解:(1)检查对应版本(Debug)指定的.entitlements文件中的“Keychain Access Groups”键值是否与ProvisioningProfile中的Entitlements项相吻合(后者一般为前者的Prefix/Seed)。

​ (2)也可以将Build Settings > Code Signing的Provisioning Profile中对应版本(Debug)的Entitlements置空。

4、Xcode配置反应有时候不那么及时,可刷新、重置相关配置项开关(若有)或重启Xcode试试。

5、证书和Provisioning Profile文件是不是只作用在签名,删掉会影响之前的发版包吗?

个人版账号:比如发版后,发版过程提交审核了,或者提交了TestFlight审核后,这个时候删除发版证书对审核是没有影响的(不含推送证书)含有推送证书的App如果推送证书删除,会推送失效。

企业级账号:证书删除会App闪退

6、删除证书对开发的影响:

当已经打好的development/ad-hoc包,缺少对应的profile文件或者对应证书,依然可以安装。

但是出现过一次development证书失效了,然后去装上个版本的开发包,安装失败。待解??

推荐阅读更多精彩内容