深入理解iOS签名原理

5,701 阅读8分钟

前言

以下是iOS签名原理系列的文章链接

  1. 密码学之RSA加密算法
  2. Hash与对称加密算法
  3. 深入理解iOS签名原理

本篇是这个系列的最后一篇,下面进入正题

1. 名词介绍

在网络中,我们通过对信息进行数字签名,来验证信息的真实性、完整性。如果将数字签名运用到代码中,即对可执行文件(Mach-O)或脚本(代码)进行数字签名,便可保证app在签名后不被修改或损坏,保护app代码的完整性和安全性,这就是 代码签名。基于代码签名的这个特点,几乎所有的软件公司在发布app时都会对其进行代码签名,苹果公司也不例外。苹果的app签名机制能确保安装到用户苹果设备(如iPhoneiPad等)上的app都是经过苹果官方允许的。接下来,我们来详细介绍一下iOS签名原理。

数字签名是 非对称加密技术数字摘要技术(Hash) 的应用。

先了解几个iOS签名相关的名词

1.1 App ID

App ID用于标识一个或者一组App。主要有两种:

  • Explicit App ID:是app的唯一标识符,它由苹果为开发者创建的team id和app的bundle id组成。每个app都会有且仅有一个明确的Explicit App ID
  • Wildcard App ID:即通配符App ID,用于标识一组app,以*结束,如com.company.*标识以com.company开头的所有应用程序。

1.2 Certificate(即证书)

Certificate是用来给应用程序签名的,只有经过签名的应用程序才能保证他的来源是可信任的,并且代码是完整的、未经修改的。证书的后缀为.cer

在我们申请证书前,需要先申请一个CSR(即Certificate Signing Request)文件,此过程实际上是生成一对密钥(即公钥和私钥),这对密钥将保存在开发者Mac电脑的Keychain(即钥匙串访问)中,CSR文件中则包含公钥。

证书类型有很多种,这里简单介绍一下常见的:

  • iOS App Development(即开发证书),用于开发和真机调试app
  • iOS Distribution (App Store and Ad Hoc)(即分发证书),用于苹果应用市场(App Store)和内部分发渠道(Ad Hoc)
  • APNS(Apple Push Notification Service,即苹果推送证书),用于推送通知到app。
    • 与开发证书和分发证书不同的是,APNSApp ID有关。
    • APNS有两种证书,分别是用于开发环境的 iOS Apple Push Notification service SSL (Sandbox),以及用于生产环境的 Apple Push Notification service SSL (Sandbox & Production)。如果你的app有推送服务,这两种推送证书都是需要创建的。

1.3 p12文件

也叫做p12证书,因为其本身就是一个加密的证书,后缀为.p12。开发者将CSR文件发给苹果服务器,由此苹果服务器会生成Certificate文件(含公钥),接着开发者将其下载到本地,再导入钥匙串中后,就可以从钥匙串中导出p12证书。显然,p12文件里面有匹配的公钥和私钥。

注意:p12文件一般是给开发团队的其他人使用的。当别人拿到p12文件和描述文件(后面会讲到),输入正确的密码后,就可以将p12导入到他的Mac设备的钥匙串中,然后再双击描述文件,即可添加到XCode中,从而参与团队开发。

1.4 Device(即设备)

Devices中包含了苹果开发者账号中所有可用于开发和测试的设备,每台设备使用UDID来唯一标识。在苹果开发者账户每年的会员期内,你能为每个产品添加最多100 个设备。

获取UDID的方法有很多种,作者常用的是在iPhoneSafari浏览器中打开 fir.im/udid 网站即可获取设备的UDID。

1.5 Provisioning Profile(即描述文件)

一个描述文件包含了App IDCertificateDevice,其后缀为.mobileprovision。常用的有:

  • iOS App Development,用于开发时的真机调试,包含App ID、证书和设备
  • Ad Hoc,用于分发时的真机调试,同样包含App ID、证书和设备
  • App Store,用于分发到苹果应用市场,包含App ID和证书,与设备无关,且所有能访问App Store的苹果设备均可下载安装app。

描述文件的作用主要是:

  • 限制只有在苹果后台注册过的设备才可以安装
  • 限制签名只能针对某一个具体的App

描述文件中还包含Entitlements(权限信息),权限信息指明了app使用的苹果服务,如iCloud权限、推送、苹果内购等。

2. iOS签名原理

2.1 真机调试

相信大多数开发者都实际操作过【申请证书和真机调试】(网上教程也多),那么问题来了,在【开发者用XCode打包app,并将其安装到手机】的过程中,苹果具体做了什么?这就要说到苹果的iOS签名流程了,可以用这幅图概括:

说明:苹果官方有一对密钥,即私钥和公钥,私钥在苹果后台,公钥在iOS系统中(如iPhone手机在出厂后,其中就保存有苹果官方的公钥);在Mac系统打包app时也会生成一对密钥(私钥、公钥),并保存在钥匙串中。为了区分这两对密钥,将苹果官方的那对密钥记为A,即私钥A公钥A;将Mac系统生成的那对密钥记为M,也就是私钥M公钥M

下面我们分析一下 iOS的签名原理(包括签名验证):

  1. XCode在向苹果服务器申请证书前,会先向钥匙串申请一个CSR文件,同时生成一对非对称加密密钥,也就是私钥M公钥M,并将公钥M放在CSR中。

  2. XCode把CSR文件发送给苹果服务器,用于申请证书。

  3. 苹果服务器用私钥A对收到的公钥M进行签名,生成Certificate文件(即证书,后缀名为.cer,里面有公钥M)。接着对CertificateDevicesApp ID以及Entitlements一起组成的数据用私钥A进行签名,生成Provisioning Profile(即描述文件),并将它发给XCode。

  4. iOS项目在编译完成之后会生成.app文件,你可以在XCodeProject中找到它。有了.app文件,XCode先使用私钥M.app进行签名,然后,把.app描述文件一起压缩成安装包.ipa文件。

以上为签名过程。

补充说明:XCode用私钥M.app的签名分为两部分。

  1. 是对资源文件的签名,生成的签名文件名为CodeResources,存放在.app目录下的_CodeSignature文件夹中。
  2. 是对app的签名,其签名信息存放在Mach-OCode Signature中。(ps:关于Mach-O,作者以后会专门写一篇博文讲解)
  1. XCode准备把安装包安装在苹果设备(如iPhone)上。

  2. iPhone对安装包进行验证,即用公钥A验证描述文件中的签名。验证通过则说明描述文件里的数据是苹果授权的。

  3. 当第【6】步验证通过后,再用公钥A验证证书中的签名。验证通过则说明公钥M是安全可信任的。

  4. 第【7】步验证通过后,就可以取出描述文件里的数据做各种验证,包括用公钥M验证App签名,验证iPhone是否在设备列表中,App ID是否对得上,使用的权限是否跟Entitlements对应等。当这些全部验证通过,iPhone就可以安装app了。

以上就是iOS签名的流程分析了,也就是iOS签名原理。显然,苹果用了两对非对称加密密钥,进行的是双重验证,基本保证了XCode真机调试的安全性,确保app的安装行为是受到苹果管控的。

理解iOS签名原理后,再去对照实际申请证书的操作流程,相信你会有新的体会。

引申:

  • Ad Hoc分发流程与上述真机调试流程基本一致。
  • In House企业分发流程也是大同小异,只是企业签名不限制安装的设备数,只要用户在iOS系统中信任企业证书,即可安装该企业证书签名的app了。

2.2 App Store签名验证

最后说一下App Store的签名验证,它与前面提到的签名验证有所不同。当开发者将ipa包上传到App Store后,苹果后台只需要用私钥A对其签名即可。当苹果设备(如iPhone)安装从App Store下载的安装包时,会自动用设备中的公钥Aapp的签名进行验证,通过后即可正常安装。

感兴趣的同学可以去App Store下载ipa包,看看里面是否有描述文件

思考:为什么发布App Store的安装包时需要用到描述文件?如果证书描述文件过期或被废除,会影响App Store上的安装包吗?