苹果签名双向验证原理

1,292 阅读5分钟

代码签名

代码签名是对可执行文件或者脚本进行数字签名,用来确认软件在签名后未被修改或损坏的措施。

简单的代码签名

在iOS出来之前,以前的主流操作系统(Mac/Windows)软件随便从哪里下载都能运行,系统存在安全隐患,盗版软件、病毒入侵、静默安装等等。苹果希望解决这样的问题,就必须保证每一个安装到iOS上的App都是经过苹果官方允许的,那么怎样保证呢?就是通过代码签名。

如果要实现验证,最简单的方式就是通过苹果官方生成非对称加密的一对公私钥。在iOS系统中内置一个公钥,私钥由苹果后台保存,我们传App到AppStore时,苹果后台用私钥对App数据进行签名,iOS设备下载这个App后,用公钥验证这个签名,若签名正确,那么就证明这个App是由苹果后台认证过的,并且没有被修改过,这就达到了苹果的目的,确保了每一个App都是官方允许的。

如果我们iOS设备安装App只是从AppStore这一个入口,那么事情就很简单了,一个数字签名搞定。 但是实际上iOS安装App还有其他渠道,比如对于开发者而言,需要真机调试,而且苹果还开放了企业内部分发渠道,企业证书签名的App也是需要顺利安装的。 苹果需要开放这些方式安装App,那么简单的代码签名就无法实现了。

双层签名认证

iOS的双层代码签名流程这里简单梳理一下,这也不是最终的iOS签名原理,iOS的最终签名在这个基础上还要稍微加点东西。 首先这里有两个角色:一个是iOS系统,还有一个就是我们的Mac系统,因为iOS的APP开发环境在Mac系统下。所以这个依赖关系成为了苹果双层签名的基础。

  • Mac系统可以生成一对公私钥:公钥Mac私钥Mac
  • iPhone设备里内置了一个公钥,即公钥Apple,对应的是苹果服务器上的私钥Apple

签名流程如下:

1、Mac上创建一个密钥对 (公钥Mac私钥Mac),即通过“钥匙串”里边的 “从证书颁发机构请求证书” 创建,私钥存在本机,公钥包含在CertificateSigningRequest文件中。

2、将CSR文件上传至苹果服务器,苹果服务器用 私钥Apple 对CSR的哈希值进行加密,生成一个证书(证书里包含了公钥Mac和其经过私钥Apple加密过的哈希值)

3、在开发编译阶段,每次编译结束,Mac会用 私钥Mac(p12文件) 对App进行签名,并把上一步得到的证书打包进App,此时App里包含了上一步生成的证书(证书里包含了公钥Mac和其经过私钥Apple加密过的哈希值)

4、iPhone设备安装App时,先通过设备内置的公钥Apple对上一步的哈希值进行解密来获得证书,进而获得公钥Mac,如果解密成功,表示该证书是苹果服务器颁发,接下来就可以拿到 公钥Mac 对App包的签名进行解密,因为该App是通过 私钥Mac进行签名的,此时就可以验证成功进行安装。

描述文件

通过上面的签名流程进行分析,如果苹果的签名流程只有这几个过程,岂不是只要申请了一个证书,就可以安装到所有iOS设备了?

苹果为了解决应用滥用的问题,又加了两个限制:

  • 只有在苹果后台注册过的设备才能安装
  • 签名只能针对某一个具体的App 并且苹果还想控制App里面的iCloud/Push/后台运行等等权限,所以苹果把这些权限开关统称为Entitlements(授权文件),并将文件放在了一个叫做ProvisioningProfile(描述文件)文件中。

描述文件是AppleDevelop网站创建的(在Xcode中填上AppleID它会代办创建),Xcode运行时会打包进入APP内.所以我们使用CSR申请证书时,我们还要申请一个东西!! 就是描述文件!

在开发时,编译完一个 APP 后,用本地的私钥Mac对这个APP进行签名,同时把从苹果服务器得到的 Provisioning Profile 文件打包进APP里,文件名为embedded.mobileprovision,把 APP 安装到手机上.在手机安装App时,先去解密得到Provisioning Profile 文件,然后再做各种验证,做各种验证,具体包括:用公钥Mac 验证 App 签名,验证当前 iOS 设备的 ID 是否在 设备 IDs 上,AppID 与当前 App 的 ID 是否对应得上,权限是否跟 App 里 Entitlements 的描述一致等等。

因为描述文件也需要做秘钥的验证,所以我们没办法修改描述文件里的东西,否则会验证不通过,只能在苹果开发者中心去申请描述文件。

App重签名

根据上面的签名原理,App的签名是由本地Xcode来完成的,所以我们可以把一些IPA包放到我们的工程编译完成后的目录里,让Xcode误认为此IPA是我们工程编译产生的,进而用我们自己的bundleid、自己的证书对其进行签名,从而实现了App的重签名。

image.png

如果是用个人证书签名,那么需要删除IPA里的PlugIns和Watch,因为个人证书无法签名Extention。