iOS 应用的证书是怎么校验的

从重签名的改造中学到更多一点

Posted by poos on September 15, 2022

简介

近段时间的支持多账号,处理的大多是脚本平台支持相关的问题,回过头来,发现可以对iOS 如何进行 app 验证做一个总结。也是让自己更加清楚的了解到 app 的安装校验过程。

苹果为了管控app安装权限,搞了一套复杂的签名原理。思考一个问题:

如果iOS证书过期了,我们debug包就打不开了,那么appstore下载的包会怎么样呢?

通过几个现象可以侧面回答这个问题: 1、AppStore 超过一年年没有更新的app还能下载吗? 2、App发生账户转移之后,发布描述文件,证书,需要转移吗?

关于证书的概念好像只有:从钥匙串生成CSR文件、上传到apple开发者中心、然后下一步、下一步、select…然后直接生成下载,过期了就重新配一下,感觉都知道又好像只知道这样的一个过程,那么为什么要有这么多复杂的流程呢?通过反向学习,可能了解到这些:

加密解密 -> 单项散列函数 -> 数字签名 -> 证书及描述文件 -> iOS签名机制。

加密解密

根据密码的类型分类:对称加密、非对称加密

对称加密:加密、解密使用相同的密钥 非对称加密:加密、解密使用不同的密钥(公钥、私钥),也被称为公钥加密

对称加密优缺点

1
2
3
优点:加密、解密速度快

缺点:不能很好地解决密钥配送问题

非对称加密优缺点 对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
特点
- 加密密钥:一般是公开的,因此该密钥称为公钥
- 解密密钥:由消息接收者自己保管,不能公开,因此称为私钥
- 公钥、私钥是一一对应的,不能单独生成

优点:能解决密钥配送问题

缺点:加密、解密速度慢

密钥配送
- 由消息的接受者,生成一对公钥、私钥
- 将公钥发给消息的发送者
- 消息的发送者使用公钥加密消息

单向散列函数

单向散列函数,又被称为消息摘要函数(message digest function),哈希函数。

例如 MD5。

1
2
3
4
5
特点
- 根据任意长度的消息,计算出固定长度的散列值
- 计算速度快
- 消息不同,散列值也不同
- 具备单向性

常见的几种单向散列函数

1
MD5(Message Digest Algorithm)、SHA-2(Secure Hash Algorithm)等

数字签名

数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。

签名过程 每个人都有一对“钥匙”(数字身份),其中一个只有她/他本人知道(私钥),另一个公开的(公钥)。签名的时候用私钥,验证签名的时候用公钥。(又因为任何人都可以落款声称她/他就是你,因此公钥必须向接受者信任的人(身份认证机构)来注册。注册后身份认证机构给你发一份数字证书。)

发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用发送方的私钥对这个摘要进行加密,这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该报文是发送方的。

在通讯中使用数字签名一般具有以下特点: 鉴权 公钥加密系统允许任何人在发送信息时使用公钥进行加密,接收信息时使用私钥解密。当然,接收者不可能百分之百确信发送者的真实身份,而只能在密码系统未被破译的情况下才有理由确信。

完整性 传输数据的双方都总希望确认消息未在传输的过程中被修改。加密使得第三方想要读取数据十分困难,然而第三方仍然能采取可行的方法在传输的过程中修改数据。

不可抵赖 在密文背景下,抵赖这个词指的是不承认与消息有关的举动(即声称消息来自第三方)。消息的接收方可以通过数字签名来防止所有后续的抵赖行为,因为接收方可以出示签名给别人看来证明信息的来源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如何能保证这个签名是消息发送者自己签的?
- 用消息发送者的私钥进行签名

如果有人篡改了文件内容或者签名内容,会是什么结果?
- 文件哈希报文验证失败或者签名验证失败,证明内容被篡改

数字签名不能保证机密性?
- 数字签名的作用不是为了保证机密性,仅仅是为了能够识别内容有没有被篡改


数字签名的作用
- 确认消息的完整性
- 识别消息是否被篡改
- 防止消息发送人否认


数字签名无法解决的问题:中间人攻击,如果遭遇了中间人攻击,那么
- 公钥将是伪造的
- 数字签名将失效
[数字证书(三):中间人攻击](https://zhuanlan.zhihu.com/p/384967640)

证书及描述文件的相关名词

证书签名请求(CERTIFICATE SIGNING REQUEST)

这个文件是在本地生成密钥对(一个公钥,一个私钥)时创建。用苹果的公钥(每个Mac OS里会有),将生成的公钥以及填写的个人信息签名后生成的文件。这个文件的作用是在开发者中心向苹果申请证书(消息推送证书、开发者证书等)时需要上传,苹果用来验证开发者身份文件的体现为.csr文件

证书(CERTIFICATES)

即上面的数字签名中的数字证书,即表示之前生成的密钥对被签名认可。文件的体现为.cer文件

P12

证书的另一种存在格式。从根证书导出的包含证书信息,密钥信息的文件。文件的体现为.p12文件

授权文件(PROVISIONING PROFILE)

授权文件就是苹果授权允许你能做的事情的集合。包含了App需要用到的证书、设备、服务等信息,苹果用私钥加密,在Mac上可以用苹果的公钥解密,用于代码签名。iOS使用的是后缀为.mobileprovision文件

苹果的签名机制

生成证书

1、创建.certSigningRequest文件,这时候会生成一对公私钥,这里称为公钥L(L:Local),私钥L。.certSigningRequest文件保存着公钥L

2、iOS 以及 mac OS上的AppleWWDRCA.cer 证书保存的就是苹果的公钥A(A:Apple),而对应的私钥A则在苹果的后台

3、在苹果开发者网站上创建证书的时候,上传.certSigningRequest文件其实就是把公钥L传到苹果后台,用苹果后台里的私钥A去签名公钥L,得到对应的证书,把证书下载回来双击安装,会跟对应的私钥L绑定一起保存在keychain中

生成描述文件

1、除了证书,还需要对应的Provisioning Profile。在苹果开发者网站上:

  • 设置App的Bundle ID
  • 设置可安装该App的设备UDID
  • 设置该App的权限
  • 设置可以使用的证书
  • 最后会使用私钥A把以上这些数据进行签名,组成一个Provisioning Profile,格式为.mobileprovision,下载回来双击安装,会保存在~/Library/MobileDevice/Provisioning Profiles中,文件名为它的UUID

开发包,企业包打包

1、签名:当需要把一个App安装在iOS设备上时,都会先把iOS项目编译打包成.app文件,而打包成可安装在iOS设备上的.app文件的前提是,设置该App的Provisioning Profile,最后使用合法的证书对源代码编译后的各种文件进行签名,步骤如下:

  • 用mac OS里的公钥A验证Provisioning Profile,获取里面的信息
  • 用Provisioning Profile里面的信息验证App的Bundle ID是否对应,App的权限是否对应
  • 用公钥A验证Provisioning Profile里面的证书,再判断是否有其中一张证书在这台Mac电脑里
  • 如果上面的验证都通过了,则会从mac OS的keychain 中取出符合条件且最新创建的证书,拿到对应的私钥L
  • / 如果有.framework文件、.dylib文件、插件、watch目录下的extension,对它们分别进行签名
  • / 把Provisioning Profile改名为embedded.mobileprovision放在.app文件里面
  • / 使用私钥L对整个.app文件进行签名,得到签名信息CodeResources也放会在.app文件里面
  • 如果需要生成.ipa文件,则会把.app文件放在Payload文件夹里,把Payload文件夹和一些其他信息文件(非必要),一起压缩形成一个.ipa文件

2、安装,把.ipa文件或者.app文件安装在iOS设备上时

  • 先使用iOS设备上的公钥A对.app文件里面的embedded.mobileprovision文件进行验证,获取里面的证书
  • 再使用公钥A对embedded.mobileprovision文件里面存在的证书进行验证,取出一张对应的证书,得到公钥L
  • 使用公钥L对.app里面所有签名信息进行验证,如果验证通过,证明该.app文件是完整合法,没有被篡改的
  • 获取embedded.mobileprovision文件里面的可安装该App的设备UDID列表,判断该iOS设备是否可以安装
  • 如果前面的验证都通过,则App会安装在iOS设备上

TF包/发布包

1、在使用xcode时,xcode会用苹果的公钥去解密证书和授权文件,得到对应配置在xcode中验证及展示。在打包时,会用开发者的私钥,描述文件签名App

2、苹果后台,使用开发者公钥去验证App的有效性,所有验证通过之后再去验证授权文件中的权限。然后使用新的发布证书签名app。

https://juejin.cn/post/6844903902605737997

https://www.freesion.com/images/467/add746362c0626eea11324ba9a9978c3.png

https://www.cnblogs.com/apem/p/5244535.html

https://www.jianshu.com/p/ab43df2ce82a

https://www.freesion.com/article/95551219226/

https://www.jianshu.com/p/1ee84112b334