iOS 搞定证书中的模糊概念

697 阅读5分钟

前言

来讨论下让人模糊的证书相关的问题。

1.要证书干嘛?

第一个问题,要证书干嘛?

证书是给签名用的。

签名又是干嘛的?

签名表示我对数据做了标记,表明这是我的数据,没有经过篡改。苹果使用签名机制来限制App的分发。 如何知道数据没有被篡改过? 数据发送方A使用了一套摘要算法,对发送的数据生成一段摘要,摘要算法保证了只要数据修改,那么通过摘要算法算出来的结果一定改变。然后,A生成一对公/私钥,用私钥对这个摘要进行加密,然后和数据一起发送给B。B收到数据后,用公钥解密签名,得到摘要,然后根据同样的摘要算法对数据进行计算,将得到的结果与解密得到的摘要进行比较,如果得到的结果一致,说明数据没有被修改过。

什么是公钥私钥?

在密码学中有一个非对称加密,非对称加密需要两个密钥:公钥和私钥。私钥加密的只能用公钥解密,公钥加密的只能用私钥解密。

那和证书有什么关系?

上述流程有个问题,就是摘要算法怎么保证相同,还有就是公钥大家都有,我怎么知道这个公钥是谁的。如果B有公钥,C也有公钥,C把B的公钥替换成自己的,那么C就能伪装成B,和A进行通信,所以A必须确保这个公钥来自B,这时候我们通过证书来解决这个问题。

证书从哪来?

从一个权威的第三方来,也就是大名鼎鼎的CA机构(Certificate Authority),证书授权中心,又称证书授权机构。

证书里有什么?

签发者的公钥;签发者使用的摘要算法;证书的数字签名;到期时间等...

balabala...

所以到底为什么需要证书?

苹果需要控制App的分发,App(非越狱)要装在设备上需要保证两点:

  • App来自Apple信任的开发者。
  • 安装的设备是Apple允许的设备。 如果App被篡改过,那么是不被允许安装在苹果的设备上的。

为了知道App有没有被篡改,所以需要对App的数据进行摘要计算,得到一个摘要。接收方使用同样的摘要算法对App进行计算,如果两者计算的结果一致,说明App没有被篡改过。 为了对计算结果,也就是摘要进行保护,所以发送方对它进行了加密,使用的是非对称加密,公私钥来自CA机构颁发的证书,证书中还包含了发送者所使用的摘要算法等其他数据。 这就是需要证书的原因。

2.其他相关概念

列举一下相关的概念:

  1. CSR文件(Certificate Signing Request)
  2. Certificates
  3. Identifiers
  4. Devices
  5. Provisioning Profile
  6. p12
  7. Entitlements

首先是这个CSR文件,英文 Certficate Signing Request,证书签名请求。在Mac的keychain的证书助理可以向CA机构申请CSR:

然后再到苹果的后台,创建一份证书,在下图的 Certificates 中:

创建出来,download到本地的是一份 .cer 文件,这个就是开发用的证书。这份证书只包含了公钥,所以它不具备签名能力,私钥是保存在生成证书的那台机器的keychain里的,如果其他开发人员也需要使用这份证书,就需要从生成证书的机器中导出包含公钥以及私钥的p12文件(个人信息交换文件),团队成员将 p12 文件装到自己电脑的 keychain,这样的证书环境才是完整的。 Identifiers:一个 Bundle id 对应一个 Identifier,也就是一个 app 对应一个唯一标识。 Devices:Devices 是这个 app 支持哪些设备进行调整,用 UDID 来作为设备的唯一标识符。 Profiles:通过这个配置生成出来的是 Provisoning Profile 文件,是 .mobileprovision 类型的文件,这个文件就是将上面提到的几个信息(不包括p12),都打包在内,本质上是一个plist文件,包含到不只以下内容:

  1. AppIdName
  2. ApplicationIdentifierPrefix
  3. CreationDate
  4. DevelopCertificates
  5. Entitlements
  6. ExpiirationDate
  7. ProvisionedDevice
  8. UUID 可以通过命令行来查看:
security cms -D -i embedded.mobileprovision > result.plist
open result.plist

Entitlements:App 描述该 App 可以调用哪些服务的字符串,iOS 会检查这个文件,决定这个 App 是否可以调用相关功能,比如 iCloud 权限、推送、健康服务等。

3.打包和验证流程

在打包时,App会调用 codesign 对 Product.app 进行签名,创建一个额外的目录 _CodeSignature 以 plist 的方式存放安装包内的每一个文件签名。 代码签名会直接写入到 mach-o 的可执行文件里,值得注意的是签名是以(Page)为单位的,而不是整个文件签名。 App的安装验证流程:

  • embedded.mobileprovision 取出证书,验证证书是否来自 Apple 信任的开发者
  • 证书验证通过后,从证书中取出 A 的公钥
  • 读取 _CodeSignatire 中的签名结果,用 A 的公钥验证每个文件的签名是否正确
  • 文件 embedded.mobileprovision 验证通过后,读取里面的设备 id 列表,判断当前设备是否可安装(App Store 和企业证书不做这步验证)
  • 验证通过后,安装 App

启动 App 的时候:

  • 验证 bundle id、entitlements 和 embedded.mobileprovision 中的 Appid、entitlements 是否一致
  • 判断 device id 包含在 embedded.mobileprovision 里
    • App Store 和企业证书不做验证
  • 如果是企业证书,验证用户是否信任企业证书
  • App 启动后,当缺页中断(page fault)发生的时候,系统会把对应的 mach-o 页读入物理内存,然后验证这个 page 签名是否正确
  • 以上验证都通过,App 才能正常启动

4.引用

关于iOS证书,你必须了解的知识

深入浅出iOS编译