Apple App签名机制

概览

  • 数字签名
  • 签名机制与验证过程
  • 操作流程

数字签名

  摘要算法

  1. 将任意长度文本通过一个算法得到一个固定长度的文本。 
  2. 源文本不同,计算结果必然不同 
  3. 无法从结果反推源

  例如,MD5和SHA算法

  非对称加密

  1. 即加密密钥与解密密钥不同,且成对出现 
  2. 对外公开的称为公钥,这对密钥生成者才拥有的称为私钥 
  3. 通过私钥加密的密文只能通过公钥解密,反之亦然 

  例如,RSA算法,非对称加密加解密比较耗时,实际使用中,往往与对称加密和摘要算法结合使用

 

数字签名的作用是我对某一份数据打了个标记,表示我认可了这份数据(签了个名),然后我发送给其他人,其他人可以知道这份数据是经过我认证的,数据没有被篡改过。

哪怎么做呢?

  1. 生成一份非对称加密的公钥和私钥,私钥自己拿着,公钥发布出去。
  2. 用一种算法,算出原始数据的摘要。常用的算法是MD5。

对一份数据,算出摘要之后,用私钥加密这个摘要,得到一份加密后的数据,称为原始数据的签名。把它跟原始数据一起发送给用户。

用户收到数据和签名后,用公钥解密得到摘要,同时用户用同样的算法计算原始数据的摘要,比对这里计算出来的摘要和公钥解密签名得到的摘要是否相等,若相等则表示这份数据中途没有被篡改过,因为如果有篡改,摘要会变化。

签名机制与验证过程

  最简单的签名  

苹果官方生成一对公私钥,在iOS里内置一个公钥,私钥由苹果后台保存,我们传App上AppStore时,苹果后台用私钥对App数据进行签名,iOS系统下载这个App后,用公钥验证这个签名,若签名正确,这个App肯定由苹果后台认证的,并且没有被修改过,也就达到了苹果的需求:保证安装的每一个App都是经过苹果认证允许的。

 
但是实际上开发APP还有其他渠道来安装。
  • 开发App时可以直接把开发中的应用安装进手机调试;
  • In-House企业内部分发,可以直接安装企业证书签名后的App;
  • AD-Hoc相当于企业分发的限制版,限制安装设备数量。
 

iOS的双层代码签名

  安装包不需要传到苹果服务器,经过苹果认证后,可以直接安装到手机上。

生成签名

  1. 在Mac开发机器生成一对公私钥,这里称公钥L,私钥L;
  2. 把公钥L上传到苹果后台,用苹果后台里的私钥A去签名公钥L。得到一份数据包含了公钥L以及其签名,把这份数据称为证书;
  3. 编译完一个 APP 后,用本地的私钥 M(今后你导出的P12) 对这个 APP 进行签名,同时把第三步得到的证书一起打包进 APP 里;

认证过程

  1. 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确;
  2. 验证证书后确保了公钥 L 是苹果认证过的,再用公钥 L 去验证 APP 的签名。

这里就间接验证了这个 APP 安装行为是否经过苹果官方允许。

但是这种签名方式并不能解决应用滥用的问题,所以苹果又加了两个限制.第一限制在苹果后台注册过的设备才可以安装.第二限制签名只能针对某一个具体的APP.并且苹果还想控制App里面的iCloud/PUSH/后台运行/调试器附加这些权限,所以苹果把这些权限开关统一称为Entitlements(授权文件).并将这个文件放在了一个叫做Provisioning Profile(描述文件)文件中。

描述文件

描述文件是在AppleDevelop网站创建,描述文件里面就是 可以安装的设备有哪些,APP的ID是什么,权限是些什么!

加上这个东西后这个签名机制是什么样呢?
 

 

生成签名

  1. 在Mac开发机器生成一对公私钥,这里称公钥L,私钥L;
  2. 把公钥L上传到苹果后台,用苹果后台里的私钥A去签名公钥L。得到一份数据包含了公钥L以及其签名,把这份数据称为证书,和一份描述文件
  3. 编译完一个 APP 后,用本地的私钥M对这个APP进行签名,同时把从苹果服务器得到的 Provisioning Profile 文件打包进APP里,文件名为embedded.mobileprovision

认证过程

  1. 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确;
  2. 通过系统内置的公钥 A,解密拿到描述文件,查看里面的设备列表时候包含当前设备;
  3. 验证证书后确保了公钥 L 是苹果认证过的,再用公钥 L 去验证 APP 的签名;
  4. 验证描述文件里的AppID是否与当前App的AppID一致,App申请的功能时候与描述文件一致;

操作流程

  • 第 1 步对应的是 keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 里面就包含公钥,私钥保存在本地电脑里.
  • 第 2 步向苹果申请对应把 CSR 传到苹果后台生成证书.
  • 第 3 步证书下载到本地.这时本地有两个证书.一个是第 1 步生成的私钥,一个是这里下载回来的证书,keychain 会把这两个证书关联起来,因为他们公私钥是对应的,在XCode选择下载回来的证书时,实际上会找到 keychain 里对应的私钥去签名.这里私钥只有生成它的这台 Mac 有,如果别的 Mac 也要编译签名这个 App 怎么办?答案是把私钥导出给其他 Mac 用,在 keychain 里导出私钥,就会存成 .p12 文件,其他 Mac 打开后就导入了这个私钥.

  • 第 4 步都是在苹果网站上操作,配置 AppID / 权限 / 设备等,最后下载 Provisioning Profile 文件。
  • 第 5 步 XCode 会通过第 3 步下载回来的证书(存着公钥),在本地找到对应的私钥(第一步生成的),用本地私钥去签名 App,并把 Provisioning Profile 文件命名为 embedded.mobileprovision 一起打包进去。所以任何本地调试的APP,都会有一个embedded.mobileprovision(描述文件)从App Store下载的没有.

说在最后

AppStore的签名验证方式有些不一样,前面我们说到最简单的签名方式,苹果在后台直接用私钥签名App就可以了,实际上苹果确实是这样做的,如果去下载一个AppStore的安装包,会发现它里面是没有embedded.mobileprovision文件的,也就是它安装和启动的流程是不依赖这个文件,验证流程也就跟上述几种类型不一样了。

据猜测,因为上传到AppStore的包苹果会重新对内容加密,原来的本地私钥签名就没有用了,需要重新签名,从AppStore下载的包苹果也并不打算控制它的有效期,不需要内置一个embedded.mobileprovision去做校验,直接在苹果用后台的私钥重新签名,iOS安装时用本地公钥验证App签名就可以了。

那为什么发布AppStore的包还是要跟开发版一样搞各种证书和Provisioning Profile?猜测因为苹果想做统一管理,Provisioning Profile里包含一些权限控制,AppID 的检验等,苹果不想在上传AppStore 包时重新用另一种协议做一遍这些验证,就不如统一把这部分放在 Provisioning Profile里,上传AppStore时只要用同样的流程验证这个 Provisioning Profile是否合法就可以了。

所以 App 上传到AppStore后,就跟你的 证书 / Provisioning Profile 都没有关系了,无论他们是否过期或被废除,都不会影响AppStore 上的安装包。

posted @ 2019-07-09 11:48  Lan_ht  阅读(1399)  评论(0编辑  收藏  举报