iOS证书管理

1、传统的新建开发者证书的流程是先通过钥匙串、证书助理创建CSR请求,创建完成以后会在本地的钥匙串中添加该证书请求的公私钥对(密钥在钥匙串中的名字就是创建CSR的时候第二行填写的名称),并且把CSR文件保存在本地磁盘中,CSR文件中包含本次创建的公钥信息。

2、登录Apple Developer开发者后台,新建一个开发者证书Certificate,选择证书的类型是开发还是发布,然后上传上一步创建的CSR文件,并生成ios_development.cer/ios_distribution.cer签名后的证书文件以供下载,下载后双击添加到钥匙串中,在“我的证书”中可以搜索到这个签名证书,若有对应私钥的话,点箭头展开可以看到该私钥。

3、如果上一步中,从开发者后台下载的是别人生成的Certificate,那么由于本地钥匙串中没有对应的私钥,所以这个证书会被放在“证书”这个分类下,而不是“我的证书”分类下。如果想用这个证书,必须从生成这个Certificate的用户的电脑里导出私钥,并在本电脑导入才可以。

4、随着Xcode的升级,证书管理不断进步,在最新的Xcode版本中,创建开发者证书简单了很多,可以完全脱离证书助理和登录Apple Developer开发者后台就可以实现了。具体做法是,在Xcode的首选项->账户这个标签页下,登录开发者账号,成功后在右侧列表里可以刷出来开发者所在组织,现在的组织类型包含两种:该账户加入Apple Developer Program开发者计划的个人开发者或者团队开发者组织,以及当前用户的个人组织(可以用来免支付开发者计划进行程序开发的单机真机调试和程序运行)。

5、选择开发者计划的组织,并且点Manage Certificates,就可以看到当前账号在当前组织下的,所有在Apple Developer开发者后台里创建过的Certificate(包含iOS Developer/Distribution/Mac Developer等等),其实这一步并不只是查询,而是同时将所有本地钥匙串中不存在属于当前用户的Certificates都下载到本地并且加入到钥匙串中,相当于与开发者后台进行了同步操作。

6、这里的左下角有个+按钮,点击后可以创建各种类型的Certificate证书,这里就是前面所说的脱离证书助理和开发者后台创建证书的快捷操作,在这里选择一个类型后,之后的流程全部自动化完成。等同于创建CSR文件、开发者创建证书、下载并导入钥匙串这些步骤。唯一的区别就是看不到磁盘上的CSR文件也没有下载的.cer证书。当然如果需要.cer的话也可以去开发者后台下载,或者从钥匙串中导出。

7、当然个人组织也可以创建证书,只是证书的签发不需要登录开发者后台(因为所有的Apple id都可以用,包括没有开通开发者计划的,这些Apple id自然没有开发者管理后台)。在个人组织下通过Manage Certificate创建证书的话,直接就将签名证书加入钥匙串里。想识别证书是通过个人组织签发的还是开发者计划在后台签发的也很容易,右键查看简介里面的组织那一行就可以看到。更简单的办法是,看证书的名字,iPhone Developer:后面如果跟的是邮箱,就是个人组织,因为没有去开发者后台签名,就得不到开发者的英文名称。相反如果后面跟的是英文名称,就是去开发者后台签名的证书。

8、当然,现在Xcode还有更方便的全自动化Certificate和Provisioning Profiles(以下简称PP文件)管理策略,就是在Xcode的项目配置里勾选Automatically manage signing。这个选项打钩以后,会自动管理从证书的创建到PP文件自动生成这所有的步骤。这个流程首先会创建App ID,注意这个App ID不会使用*通配符,一定会注册一个与Bundle Identifier一样的显式App ID,而且会检查全局唯一性,也就是说所有通过个人组织/开发者组织的账号在自动管理过程中都会在全世界范围内检查App ID的唯一性,若可以使用则注册到该个人组织/开发者组织名下,不允许再有其他人使用(自动管理生成的App ID,不管是个人组织还是开发者组织都是隐式的,没有任何地方可以查看该账号下在自动管理的情况下注册过哪些App ID,这个设置目前感觉有点反人类)。

If you enable automatic signing, Xcode does the following for you when needed:
- Creates your signing certificates
- Registers connected devices
- Creates and edits App IDs
- Manages provisioning profiles
- Edits the entitlements and information property list files

9、再下一步会根据选择的组织,来检查在钥匙串中,是否存在该组织下的开发者证书及私钥,若存在则使用最新创建的证书,若不存在则会检查是否在Accounts中登录了该组织下的开发者账号(Admin角色以上,当然这里肯定是登录了,因为组织的选择列表的数据来源就是所有登录过的Apple id所在组织的合集,只是确认是否是Admin角色可以在控制台创建证书,个人组织就没有权限这一说了),可以创建的话就会创建新的证书,并将公私钥和证书加入本地钥匙串。

10、最后一步是更新Xcode隐式维护的一个PP文件,叫做iOS Team Provisioning Profile,这个文件在开发者后台不可见,也不能手动编辑。每次都会根据当前开发者后台的最新状态重新生成并且下载到本地电脑来更新,所谓最新状态是指,使用通配符*的App ID,Certificates包含所有在开发者后台中存在的证书、Devices列表包含所有在开发后台注册的测试设备。

11、需要注意的是,以上自动流程只有在Xcode开发的时候适用。在App发布的时候,会根据选择的组织再选择一遍Certificate和PP文件,可以自动也可以手动,自动的话,会默认选择Xcode在自动在开发者后台创建的发布类PP文件(XC iOS:或者XC iOS Ad Hoc:,特殊的情况是当使用推送服务等能力时,要求必须使用显式的App ID,则Xcode会自动创建XC iOS: /app_id/或者XC iOS Ad Hoc:/app_id/)。在使用自动模式下会根据优先级匹配,能匹配到显式的App ID的话就不会使用通配符的PP文件,而且不可以手动更改发布证书和PP文件。另外一种情况,手动维护的话,只能选择用户在开发者管理后台创建的PP文件,而不能选择XC开头的Xcode自动维护的PP文件,这时需要用户手动保证PP文件里证书和Device是否覆盖完整。

12、最后一点,自动管理的缺点是,不能保证XC ***那个PP文件包含了所有最新的内容,而且找不到可以更新的地方,虽然Accounts那里有一个Download Manual Profiles的按钮,但它也只是简单的从开发者后台下载所有手工维护的PP文件,而不包含XC ***那几个自动维护的文件。所以一个笨办法是,如果发现自动管理的XC *** PP文件里面没有包含最新添加的Device,那么最简单的办法就是把原来的删掉重新从开发后台下载。目录是:/Users/用户名/Library/MobileDevice/Provisioning Profiles,想查看是否包含某个Device的UUID可以使用预览插件:brew cask install provisionql。

13、强烈推荐这个博客http://www.cnblogs.com/slegetank/p/5752114.html,写的非常清楚。不过有一行命令写错了,codesign -s 'identifier' -f xxx.app,另外这个写的也不错http://www.pchou.info/ios/2015/12/14/ios-certification-and-code-sign.html

14、给应用重签名比较麻烦,因为codesign命令只能一次性签名xxx.app中的可执行文件和所有资源文件,无法签名Framework和dylib动态链接库的内容,所以这些库还需要逐个执行codesign去签名,github有不少可用的app重签名工具,包括命令行和客户端程序。最新版本依然可以使用的包括XReSign或者ios-app-signer。

15、对于安装app时错误的解析,主要表现是安装进度条能看到是满了,但是最后一步就是不行,一般是App验证不成功。将iPhone连上Mac,打开Xcode,选择菜单上的Window——Devices,找到自己的设备名,查看右下方的log,可以类似看到下面的日志:

Aug 19 14:54:30 iphone installd[5481] <Notice>: 0x100594000 -[MIInstaller performInstallationWithError:]: Installing <MIInstallableBundle ID=cn.app.test; Version=6_1434698124, ShortVersion=1.4>
Aug 19 14:54:30 iphone misagent[5495] <Error>: attempt to install invalid profile: 0xe8008011
Aug 19 14:54:30 iphone installd[5481] <Error>: 0x100594000 -[MIInstallableBundle _installEmbeddedProfileInBundle:]: Could not install embedded profile: 0xe8008011 (Expired)

0xE8008011代表The Provisioning Profile being loaded is expired,可以确认就是Provisioning Profile过期了。
ipa安装失败时出现的各种错误码的意义:

  • 0xE8008003 - It was unable to get the Creation Date of the Provisioning Profile being loaded
  • 0xE8008010 - Provisioning Profile Version is not equal to 1 (?)
  • 0xE8008012 - The UUID of the device does not match any in the Provisioning Profile being loaded
  • 0xE8008011 - The Provisioning Profile being loaded is expired
  • 0xE8008003 - No UUID included in the Provisioning Profile that is being loaded
  • 0xE8008015 - A valid provisioning profile for this executable was not found
  • 0xe8008016 - 原因可能之一是证书名正确,Profile里的App ID不正确,可能原因2是app id正确而证书名不正确
16、通过以下命令可以查看二进制文件中的签名信息,otool -l 可执行文件名称|grep "cmd LC_CODE_SIGNATURE" -A 5
参考:
https://www.objc.io/issues/17-security/inside-code-signing/
http://www.kimbs.cn/2015/04/ios-development-code-signing/
http://blog.csdn.net/ouyangshima/article/details/53162192
https://www.jianshu.com/p/4aab15215fe7
http://www.cnblogs.com/SirSmith/p/4985571.html
http://blog.csdn.net/u011661836/article/details/51979581
http://www.makeiteasy.site/2017/03/13/study-of-signature-and-digest.html
http://blog.cnbang.net/tech/3386/
http://blog.csdn.net/Lotheve/article/details/50354099

http://help.apple.com/xcode/mac/current/
http://help.apple.com/developer-account/
https://developer.apple.com/documentation
https://forums.developer.apple.com/welcome
https://developer.apple.com/library/content/navigation/

推荐阅读更多精彩内容