基本概念
涉及的算法
- 非对称加密算法,一般是RSA加密算法。一对私钥和公钥。用私钥加密后,只能用公钥解密。知道公钥无法破解出私钥。
- 摘要算法,也是哈希算法。相同的数据,哈希值肯定相同。哈希值不同,数据肯定不同。
根据哈希值无法反推出数据是什么
。
签名算法:
发送方:
- 把原始数据计算hash
- 将hash使用私钥加密后获得加密后数据,叫做签名
- 将明文同签名一起发送给接收方。
接收方:
- 收到后使用公钥解密签名,获得原始数据的hash值。
- 自己对原始数据计算hash值。
- 将计算得出的hash和解密后的hash进行比较,就可以知道明文是否被篡改过。
证书
接收方如果要接收多个来源的数据,就需要保存多个来源的公钥,管理非常不便。所以一般会把公钥也放在发送的数据中。但这样一来,对于收到的公私是否是真的,接收方就不能确定了。为了解决这个问题,一般会使用一个可信的第三方机构,通过第三方机构对用到的公钥也做一次签名。这个第三方机构叫做证书颁发机构(Certification Authority),也就是CA。公钥及其相关签名信息整个放在一个文件里,叫做证书。
接受者一般保存CA的公钥就可以,之后验证接收的公钥合法性,再验证接收的数据的合法性。CA有时候也会有多个,形成链条。
开发者证书
只有通过iOS系统的签名校验,才能安装到手机上。开发阶段需要频繁修改文件,安装测试等,不能每次都是请求Apple进行签名才能安装。所以需要一种开发者可以给自己签名的机制,同时又能保证安全。
申请创建
一般是通过KeyChain里的证书助理,填写邮箱和名称后,创建一个.certSigningRequest文件,之后保存到磁盘上。这时在KeyChain里已经生成好了一对公钥和私钥。
提交Apple验证
之后我们会在Apple的网站上,上传这个request文件。Apple生成一个.cer证书文件,我们下载到本地后,双击安装,就可以在KeyChain里看到安装的证书。
查看安装的证书信息。
- 证书信息,App根据我们的账号生成
- 颁发机构信息
- 使用的的算法
- 公钥信息
现在开发者就具有私钥+证书。证书里包含了公钥以及苹果对公钥的签名。打包签名的过程中,就使用开发者的私钥对文件进行签名。我理解可以把开发者视为数据的发送方,Apple是第三方的证书颁发机构。CA是可以一级一级形成链条。设备上安装ipa时,系统通过Apple的签名确定公钥的合法性,最终确定安装包的合法性。
开发者证书
一般有Develop、adhoc、distribution、inhouse。不同证书运行原理是一样的,区别在Provisioning Profile文件中
除了证书外,还要两个文件会被打进包里, provisioning profile
和 entitlements
entitlements
这个文件与沙盒运行机制有关。iOS系统里每个App只能运行在自己的沙盒环境中,对资源的访问,只能限定在自己的沙盒中,比如磁盘文件的访问。并且对每个App使用权限做了严格的限制,只要是App用到的系统权限,必须在这个entitlements文件里做声明,否则运行时会直接Crash。
provisioning profile
这个文件是我们再Apple的网站上生成的,在构建时会被打进安装包,并重命名为 embedded.mobileprovision
。这个文件起到了的作用是,将签名的证书,与开发者账号、运行的设备、以及使用的权限做一个绑定。(在Apple网站上我们创建这个文件时,需要选择cer证书、设备、entitlements)。
这是一个处理过的plist文件,使用一些工具(比如python的PyMobileProvision库)就可以看到这个文件里至少包含以下信息:
账号信息
1
2'AppIDName': 'testapp',
'ApplicationIdentifierPrefix': ['TeamID'],证书
1
DeveloperCertificates': [Common Name: iPhone Distribution: xxxxx, SHA256: 9B766E84FC3C4FC587BBB433866110A82C6B59871214B84A07DA5321FAE315C2],
Entitlements列表
1
2
3
4
5
6
7
8'Entitlements': {'application-identifier': 'xxxx.com.test.testapp',
'aps-environment': 'production',
'com.apple.developer.applesignin': ['Default'],
'com.apple.developer.associated-domains': '*',
'com.apple.developer.team-identifier': '{TeamID}',
'com.apple.security.application-groups': ['group.com.test.testapp.appgroup'],
'get-task-allow': False,
'keychain-access-groups': ['TeamID.*']},ProvisionedDevices。注册过的设备
1
2
3
4
5'ProvisionedDevices': ['201f303409994384c1916d12e0a069fb86962ead',
'b6f474870760ccffbec436cb8aceb8f80c814602',
'00008006-0004929A36E2002E',
'85b3d893b249672891ed360a02e179be6174dfa8',
...企业版可以安装在任意的设备上,它的Provisioning profile里没有描述注册设备的字段,而是这样的
1
'ProvisionsAllDevices': True,
签名相关文件的处理
证书在构建时,会一起打进安装包里,会重命名为
certificate.cer
。provisitioning profile文件会被重命名为embedded.mobileprovision
。
构建时签名过程
每一次build中都会涉及签名过程,包括framework和主项目二进制。使用的证书是provisioning profile里配好的。比如
在生成的安装包中, 还会生成一个文件夹
里面是一个plist格式的文件,包含了所有资源文件的md5值。
二进制制的签名信息会嵌入到二进制文件里,包括主项目和framework。二进制里会增加一个段
验证
在App安装,启动,运行等不同阶段,系统会进行一些合法性校验。有了前面的各种铺垫,我们大概可以了解,系统从证书颁发机构的合法性校验开始(Root CA的公钥是内置在设备系统里的,所以证书校验链条最上层的公钥不需要提供),逐步验证证书的合法性、公钥的合法性,直到App包里文件的合法性。
关于商店包
关于商店包会有几个疑问:
- 我们的证书都是有一年期限的,过期之后就不能使用,过期后不能安装用该证书签名的App。但是商店包没有这个影响。
- 商店包里没有
embedded.mobileprovision和certificate.cer
原因bang在他的博客里提到,是因为Apple在安装包上传之后,Apple用自己的私钥对安装包做了重签名。所以我们自己的证书,profile文件就没有用处了。同时也就没有证书有效期的限制了。
参考
主要是参考了这篇博客,讲解的很深入
http://xelz.info/blog/2019/01/11/ios-code-signature/
http://blog.cnbang.net/tech/3386/