加点东西:
上述流程只解决了上面的第一个需求,也就是需要经过苹果的允许才可以安装,还未解决第二个避免被滥用的问题。怎么解决呢?苹果加了两个限制,一个是限制在苹果后天注册过的设备才可以安装,二是限制签名只能针对某个具体的App。
在上述的第三步中,苹果用私钥A去签名我们本地公钥L时,实际上除了签名公钥L,还可以加上很多数据,这些数据都可以保证是经过苹果官方认证的,不会有被篡改的可能,那么我们就可以把AppID和设备ID添加进去:
![d74bf932b2e82cb3cb21e1ef5f2728e9.png](https://img-blog.csdnimg.cn/img_convert/d74bf932b2e82cb3cb21e1ef5f2728e9.png)
把允许安装的设备ID和APP对应的AppID等数据,都在第三步这里和公钥L一起,被私钥A签名,一起组成证书。在第五步验证时就可以拿到设备ID列表,判断当前设备是否符合要求。
最终流程:
到这里这个证书已经变得很复杂了,有很多额外的信息,实际上除了设备ID,AppID,还有其他信息也需要用苹果签名,像App里面的iCloud,后天运行等苹果都想控制,苹果把这些权限开关统称为entitlements,它也需要通过签名去授权。
但是一个证书本来就有规范的格式,我们把这些杂七杂八的额外信息赛入证书是不合适的,因此苹果另外搞了一个东西叫Provisioning Profile,一个Provisioning Profile里面就包含了证书以及上述提到的所有额外信息,以及所有信息的签名。
所以最终流程就变成了这样:
![4e56903c55a28574ed941def7201ad99.png](https://img-blog.csdnimg.cn/img_convert/4e56903c55a28574ed941def7201ad99.png)
1.在你的Mac上生成一对公钥和私钥,称为公钥L和私钥L。
2.苹果自己有一对固定的公钥和私钥,私钥在苹果后台,公钥内置在iOS设备中,分别称为私钥A和公钥A。
3.把公钥L传到苹果后天,用苹果后天的私钥A去签名公钥L,得到一份数据包括公钥L和签名,这份数据称为证书。
4.在苹果后台申请好AppID,配置好设备ID列表,App权限开关,再加上第三步的证书,组成的数据用苹果后天的私钥A签名,把数据和签名一起组成一个Provisioning Profile文件,下载到本地Mac。
5.在开发时,编译完一个App后,用本地的私钥L对这个App进行签名,同时把第四步生成的Provisionning Profile一起打包进App里,文件名为embeded.mobileprovision,把App安装到手机。
6.在安装时,就可以使用iOS设备里内置的公钥A来验证Provisioning Profile的数字签名是否正确。
7.如果数字签名没有问题,那么就能确保设备ID,AppID,entitlements,和App都是经过苹果认证的,可以安装到iOS设备上。
上面的步骤对应我们平时具体操作和概念是这样的:
1.第一步对应的是从keychain里“从这证书颁发机构请求证书”,这样就在本地生成了一对公私钥,保存的额CertificateSigningRequest就是公钥,公钥保存在本地电脑里。
2.第二步苹果处理,不用管。
3.第三步把CertificateSigningRequest上传到苹果后天,生成证书,并下载到本地。
4.第四步是在苹果网站操作的,配置AppID,设备ID,权限等,生成Provisioning Profile文件,并下载Provisioning Profile文件到本地。
5.xcode通过第三步下载下来的证书,去找对应的本地私钥,用本地私钥去签名App,并把Provisioning Profile文件一起打包进去,安装进iOS设备。
总结一些概念:
1.证书:内容是公钥或者私钥,由其它机构对其签名组成的数据包。
2.entitlements:包含了App权限开关列表,AppID,设备ID等。
3.CertificateSigningRequest:本地公钥。
4.p12:本地私钥。
5.Provisioning Profile:包含证书,entitlements等数据,并由苹果后台私钥签名的数据包。
我们平时的操作:
按照上面的流程,那么对于开发人员来说,应该是我们每次新建一个项目也就是有一个新的AppID时,都应该去申请一对本地公私钥,上传公钥到苹果后台,然后下载证书,但是实际上我们并没有这么做,好像很少需要去keychain请求本地公私钥,这是为什么呢?
这里的原因就是iOS Team Provisioning Profile。
iOS Team Provisioning Profile是第一次使用xcode添加设备时,xcode自动生成的,它包含了xcode生成的一个Wildcard AppID(匹配所有应用程序,账户里面的所有device,所有Development Certificates),因此team中的所有成员都可以使用这个iOS Team Provisioning Profile在team的所有设备上调试所有的应用程序,并且当有新设别添加进来时,xcode会更新这个文件。
![5ea1678e6c7aa51e85165994923baca9.png](https://img-blog.csdnimg.cn/img_convert/5ea1678e6c7aa51e85165994923baca9.png)
如此一来,只要我们有一对本地公私钥,并且通过这个本地的公钥上传给苹果获取了证书,那么以后我们运行任何App,在任何iOS设备上运行,都可以使用这个本地私钥和证书,而没有必要每次去创建新的公私钥和获取证书。
下面我从我的项目中找出一个iOS Team Provisioning Profile,我们可以一起来看一下它的结构:
![b00e5c1f2a1952cc985e57e63562e559.png](https://img-blog.csdnimg.cn/img_convert/b00e5c1f2a1952cc985e57e63562e559.png)
第一个是AppID,这里的AppID是我当前应用的AppID。
第二个是证书,这就是选择了我本地的一个证书,是上面的流程中上传本地的公钥得到的证书。
第三个是team,这个是我在项目中选择的,这个team决定了我用哪个证书。
第五个是entitlements,就是一系列的权限开关。
通过这个iOS Team Provisioning Profile的结构我们就能明白,iOS Team Provisioning Profile中保存着很多分证书,很多AppID,很多设备ID,entitlements。当我们需要在一个指定的iOS设备上运行一个指定的App时,iOS Team Provisioning Profile就会得到这个AppID和这个设备ID以及它对应entitlements,组成这个特定的Provisioning Profile,打包进APP里面。这样就不需要我们每次去申请证书,生成Provisioning Profile文件了,非常方便。
注:这篇文章主要是把文章摘抄了一遍,由于作者写的太好了,让我茅塞顿开,于是想重新写一次加深理解,也方便以后查阅。
![db159b1ee8666447ca995b1875c51b8d.png](https://img-blog.csdnimg.cn/img_convert/db159b1ee8666447ca995b1875c51b8d.png)