iOS App 签名原理

笔者接触打包已经一段时间了,但一直对签名都是似懂非懂,最近从加密数论知识起回看这部分知识,感受仍是有不少不懂的地方。html

先简单说明一哈数学原理,而后说RSA 算法密钥生成的步骤,最后回到 iOS 签名打包,以及分享一哈利用重签名作过的坏事(以学习、省时间为目的)。git

非对称加密

对称加密是经过同一份密钥加密和解密数据;而非对称加密则有两份密钥,分别是公钥和私钥,用公钥加密的数据,要用私钥才能解密,用私钥加密的数据,要用公钥才能解密。github

(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人均可以得到,私钥则是保密的。 (2)甲方获取乙方的公钥,而后用它对信息加密。 (3)乙方获得加密后的信息,用私钥解密。算法


数学原理

数学原理太长(难)不看篇:有一条等式,三个数字能够关联起来,从而达到互相验证对方的数字是否配对。若是已知数字验证等式很容易,可是若是未知这些数字,要推测出来对方的数字目前的技术还十分艰难。安全

互质的简单结论

关于互质关系,咱们不可贵出如下结论:微信

  1. 任意两个质数互质。网络

  2. 一个数是质数,另外一个数只要不是它的倍数,两数互质。app

  3. 一个质数与比它小的数,两数互质。函数

  4. 1 和任意天然数互质。post

  5. p 是大于1的整数,p 和 p - 1互质。

  6. p 是大于1的奇数,p 和 p - 2互质。

欧拉函数

思考下面这个问题。

任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?

计算这个值的方法就叫作欧拉函数 ,以φ(n) 表示。

  • 若是n = 1,则φ(1) = 1 。

  • 若是n是质数,则 φ(n)=n-1 。由以上结论(3)得出。

  • 若是 n = p^k (p为质数,k为大于等于1的整数),那么

image.png

由于 n 的因数只有 一、p、n,因此只要一个数因数分解不包含质数 p,才可能与 n 互质。

而比p小,包含质数 p 的数有 1 *p、2 * p、3 * p、...、p^(k-1)×p,共有 p^(k-1) 个。减去便可。

好比 φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4。

  • 若是 n 能够分解成两个互质 的整数之积。

  • n = p1 * p2

网上有种证实是“中国剩余定理”,看不懂🙈。。。说说本身的理解。

好比 35 = 5 * 7。因为35 的因数只有一、五、七、35。对于比35小的数来讲,有7个5的倍数,5个7的倍数,则有12个,因为35是重复计算的,则有11个。因此结果是 35 - 24 = 11。

**φ(n) = p1 * p2 - p1 - p2 + 1 = (p1 - 1)(p2 -1) = φ(p1)φ(p2) **

  • 由于任意大于1的正整数,均可以由一系列质数相乘所得。

image.png

根据第四条,注意是要互质的数 ,可得

image.png

再根据第三条,可得

image.png

image.png

这就是欧拉函数 。

欧拉定理

欧拉定理是RSA算法的核心。理解了这个定理,就可能能够理解RSA。

直接给结论。感兴趣的能够本身去看证实(我也想看懂,但懵懵懂懂)。

image.png

即 a的φ(n)次方被n除的余数为1。

这个定理结合取余分配率能够用来简化幂的模运算。

(ab)%c=(a%cb%c)%c

image.png

费马小定理。

假设正整数 a 与质数 p 互质,n = p的状况下,由结论(3)可得:

image.png

image.png

模反元素

若是 a 和 n 互质,那么必定能够找到整数 b,使得 ab - 1 被 n 整除。这时,b 就叫作 a 的“模反元素”。不难发现,若是b是模反元素,那么b + a、b - a也是模反元素,模反元素不止一个 。

image.png

欧拉定理能够用来证实模反元素必然存在。

image.png

密钥生成的步骤

假设龙神要与那个ta 进行加密通讯,他要怎么作才能瞒过八卦的群众呢?

第一步,随机选择两个不相等的质数 。

龙神的幸运数字是61 那个ta 的幸运数字是53。

第二步,相乘。

n = 61 * 53 = 3233

写成二进制是 110010100001,一共有12位,因此这个密钥是12位。(一般1024位,更安全的场合2048位)。

**第三步,计算n的欧拉函数φ(n)。 **

φ(n) = (p-1)(q-1),φ(3233) = 3120。

**第四步,随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质。 **

龙神选了17。

第五步,计算e对于φ(n) 的模反元素d。

ed ≡ 1 (mod φ(n))

等价于

ed - 1 = kφ(n)

ex + φ(n)y = 1

17x + 3120y = 1

龙神算出一组整数解为(2753,-15),即 d = 2753。

第六步,将 n 和 e 封装成公钥,n 和 d 封装成私钥。

因此公钥(3233,17),私钥(3233,2753)。

第七步, RSA 的可靠性。

回顾上面的步骤,一共出现了六个数字。

p = 61 q = 53 n = p * q = 3233 φ(n) = (p-1)(q-1) = 3120 e = 17 d = 2753

咱们上面提过,公钥是公开的,因此 n 和 e 都是全部人能知道的。关键是d,若是泄漏了,就等于私钥泄漏。

那么,在已知 n 和 e 的状况下,怎么推导出 d?

(1) ed≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。

(2) φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。

(3) n=pq。只有将n因数分解,才能算出p和q。

因此,只要因数分解n,就能够获得d。

可是,对于一个很大的质数,要因数分解是很是困难的事 。

因此,以目前的技术来看, RSA 是可靠的 。

加密和解密

公钥:e 和 n 私钥:d 和 n 明文:m 密文:c

公钥和私钥经过一条等式能互相验证。有兴趣的能够本身研究。

RSA算法原理(二)

image.png

加密

假设龙神想说的悄悄话m,他就要用公钥(3233,17)进行一次加密。这里必须注意,m是小于n的整数。

而后算出下面式的c:

m^e ≡ c (mod n)

假设龙神说的悄悄话是 65,算出c 为2790。

咱们要用到欧拉定理

65^17 mod 3233 = 2790

因此龙神就把2790发给那个ta。

解密

那个ta 收到2790后,就用私钥(3233,2753)进行解密。

c^d ≡ m (mod n)

2790 ^ 2753 ≡ 65 (mod 3233)

因此原文就是65。

RSA 的优缺点

优势: 目前来讲安全。

缺点:

  • 速度慢

  • 只适合加密小数据


简单介绍完一番我没彻底理解的数学理论后,下面进入签名环节。

数字签名

做用

数字签名的做用是利用非对称加密方法,本身持有私钥,公布公钥。互相加密以及验证消息来源。

步骤

  1. 首先用一种算法,算出原始数据的摘要。需知足

    a. 若原始数据有任何变化,计算出来的摘要值都会变化。

    b. 摘要要够短。这里最经常使用的算法是MD5 。

  2. 生成一份非对称加密的公钥和私钥,私钥保留,公钥公布出去。

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

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

image.png

最简单的签名

image.png

iOS 设备用公钥验证一遍就知道该 App 是否是通过苹果后台认证的。若是被篡改过,确定是不行的。

然而,App 除了从 AppStore 下载,还有三种方式安装:

  1. 开发 App 时能够直接把开发中的应用安装进手机进行调试。

  2. In-House 企业内部分发,能够直接安装企业证书签名后的 APP。

  3. AD-Hoc 至关于企业分发的限制版,限制安装设备数量,较少用。

因此苹果的签名还有额外的事情要作。

苹果的 App 签名

咱们来考虑上面第一种状况。

首先,它既要有能不经苹果私钥验证,立刻安装的便利,又要通过苹果验证。

听起来有点绕。苹果采用的方案是双层签名。

image.png

  1. 在 Mac 生成一对公私钥,这里称为公钥L私钥L

  2. 苹果本身有固定的一对公私钥,私钥在苹果后台,公钥在每一个 iOS 设备上。

  3. 把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L。获得一份数据包含了公钥 L 以及其签名,把这份数据称为证书 。

  4. 在开发时,编译完一个 APP 后,用本地的私钥 L 对这个 APP 进行签名,同时把第三步获得的证书一块儿打包进 APP 里,安装到手机上。

  5. 在安装时,iOS 系统取得证书,经过系统内置的公钥 A,去验证证书的数字签名是否正确。

  6. 验证证书后确保了公钥 L 是苹果认证过的,再用公钥 L 去验证 APP 的签名,这里就间接验证了这个 APP 安装行为是否通过苹果官方容许。(这里只验证安装行为,不验证APP 是否被改动,由于开发阶段 APP 内容老是不断变化的,苹果不须要管。)


除了要保证通过验证外,苹果还要防止滥用这种途径下载。

想象一下,把真机连到 Mac 上,不就能想装多少装多少 App 吗?那多部设备连到 Mac 上,App 不就能想装在哪装在哪吗?

苹果的方案是识别 设备和 App

想调试的设备必需要到开发者网站申请,而且设备数量是有限制的。

而后还针对每一个Bundle Identifier(App ID)配不一样的证书。

这两种数据都在上面第三步一块儿组成证书(暂且这么认为)。

至此,证书就能实现 通过苹果认证,而且能限制安装设备数量和 App ID 。

固然,证书不止有这些信息,还有推送等权限,苹果把这些权限开关统一称为Entitlements 。若是App 一开始的证书没申请推送权限,那么后面新增权限后,须要更新配置。

实际上,一个“证书”有规定的格式规范,不该把这些额外的信息往里塞。因此上面的暂且这么认为部分是不对的。

因此苹果把证书和额外信息包装起来 ,把它叫作 Provisioning Profile 。

因此能拓展整个流程图以下。

image.png

  1. 在你的 Mac 开发机器生成一对公私钥,这里称为公钥L,私钥L。L:Local
  2. 苹果本身有固定的一对公私钥,跟上面 AppStore 例子同样,私钥在苹果后台,公钥在每一个 iOS 设备上。这里称为公钥A,私钥A。A:Apple
  3. 把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L。获得一份数据包含了公钥 L 以及其签名,把这份数据称为证书。
  4. 在苹果后台申请 AppID,配置好设备 ID 列表和 APP 可以使用的权限,再加上第③步的证书,组成的数据用私钥 A 签名,把数据和签名一块儿组成一个 Provisioning Profile 文件,下载到本地 Mac 开发机。
  5. 在开发时,编译完一个 APP 后,用本地的私钥 L 对这个 APP 进行签名,同时把第④步获得的 Provisioning Profile 文件打包进 APP 里,文件名为 embedded.mobileprovision,把 APP 安装到手机上。
  6. 在安装时,iOS 系统取得证书,经过系统内置的公钥 A,去验证 embedded.mobileprovision 的数字签名是否正确,里面的证书签名也会再验一遍。
  7. 确保了 embedded.mobileprovision 里的数据都是苹果受权之后,就能够取出里面的数据,作各类验证,包括用公钥 L 验证APP签名,验证设备 ID 是否在 ID 列表上,AppID 是否对应得上,权限开关是否跟 APP 里的 Entitlements 对应等。

关于证书等概念

上面的步骤对应到咱们日常具体的操做和概念是这样的:

  1. 第 1 步对应的是 keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 就是公钥,私钥保存在本地电脑里。
  2. 第 2 步苹果处理,不用管。
  3. 第 3 步对应把 CertificateSigningRequest 传到苹果后台生成证书,并下载到本地。这时本地有两个证书,一个是第 1 步生成的,一个是这里下载回来的,keychain 会把这两个证书关联起来,由于他们公私钥是对应的,在XCode选择下载回来的证书时,实际上会找到 keychain 里对应的私钥去签名。这里私钥只有生成它的这台 Mac 有,若是别的 Mac 也要编译签名这个 App 怎么办?答案是把私钥导出给其余 Mac 用,在 keychain 里导出私钥,就会存成 .p12 文件,其余 Mac 打开后就导入了这个私钥。
  4. 第 4 步都是在苹果网站上操做,配置 AppID / 权限 / 设备等,最后下载 Provisioning Profile 文件。
  5. 第 5 步 XCode 会经过第 3 步下载回来的证书(存着公钥),在本地找到对应的私钥(第一步生成的),用本地私钥去签名 App,并把 Provisioning Profile 文件命名为 embedded.mobileprovision 一块儿打包进去。这里对 App 的签名数据保存分两部分,Mach-O 可执行文件会把签名直接写入这个文件里,其余资源文件则会保存在 _CodeSignature 目录下。 第 6 – 7 步的打包和验证都是 Xcode 和 iOS 系统自动作的事。
  • CSR:Certificate Singing Request,证书签名请求文件。

包含电脑的公钥信息。因此建立时不须要填任何和发布等有关的信息。

  • Certificates证书:发布者证书。Apple Develop的ID 对某部电脑的受权证书。

内容是公钥或私钥,由其余机构对其签名组成的数据包。

电脑拥有这个证书后,有权对该Apple Developer的ID下全部App进行真机测试、打包、发布。注意这里,并未指定App,换句话说,和App无关。

  • CSR 和 Certificates 的联系

上面提到了Certificates包含了电脑的信息,这个信息来自于CSR。因此在建立Certificates时,须要提交CSR。至关于 Mac 的公钥被苹果私钥 加密的过程。

  • p12: 本地私钥,能够导入到其余电脑。

上面提到,拥有证书才有权作那些事。若是另外一部电脑想发布,也须要证书。若是又建立一个新证书也能解决,但通常一个开发者账号建立一个发布证书就够了,并且苹果对这证书数量有限制。这时候导出p12文件,至关于拷贝了一份私钥。给另外一部电脑安装后,另外一部电脑就有权了。

  • Entitlements:包含了 App 权限开关等信息。

  • Provisioning Profile: 描述文件。包含了证书、App ID、设备、Entitlements 等数据,并由后台私钥签名的数据包。也称为PP文件,.mobileprovision后缀文件。

小结

CSR文件包含本地公钥,被苹果私钥加密后生成 Cer 证书。该证书与权限、App ID、设备等数据经苹果私钥加密后生成 PP文件。装到真机时,会对 PP文件总体进行验证,还会对 PP 文件中的 Cer 证书进行验证。


苹果的 App 验证

上面说了开发包的验证流程

实际上 App 安装以及每次启动都会验证。

各类证书的有效期

企业账号发布证书有效期是3年,而开发证书有效期为1年,而描述文件开发发布都是只有1年有效期。

我的账号开发证书发布证书有效期都是1年,描述文件也全是1年有效期。


下面再说说企业包 和 AD - Hoc以及 App Store的验证流程。

企业包和 AD - Hoc包验证流程

企业包和 AD -Hoc 的区别在于企业包不会限制安装设备数量,而且须要信任证书。

由于这两种包不通过 App Store,对App的签名是用证书签名的。因此证书经苹果发布后,苹果还想要限制的话,就必须检查证书是否过时。这个步骤被放到了启动 App 时。

所以,若是证书过时或者 revoke掉,开发者帐号被封禁,都会致使 App 启动时闪退

  1. 证书过时或 revoke
  • app 会立刻不能使用,而且因为 PP 文件包含它,也会失效。
  1. PP 文件过时 或 revoke
  • 也会闪退,但可能不会立刻反应过来,可能因为网络缘由等,不能立刻验证失效。
  1. 帐号被注销
  • 闪退

App Store 的验证流程

blog.cnbang.net/wp-content/…

其实就是最简单的验证流程。

咱们上传 App 到 App Store时验证咱们的证书、PP文件。今后,与咱们的文件再无关系。

上传后,苹果在后台直接用私钥签名 App 就能够了。若是去下载一个 AppStore 的安装包,会发现它里面是没有 embedded.mobileprovision 文件的,也就是它安装和启动的流程是不依赖这个文件,验证流程也就跟上述几种类型不同了。

已经在苹果商店下载安装的app不受影响(不管是过时仍是Revoke,甚至是开发者帐号被注销,由于这个时候,对于app的签名,是经过苹果私钥直接签名的,没有使用开发者名下的私钥签名)。

但App Store 会下架相关的 App。


笔者以前遇到一个场景就是,违规操做被注销是没办法的(注意保护开发者帐号,能够开启双重验证,不要被偷去作马甲包而后被举报了)。那么对于企业包证书过时问题怎么处理呢?

由于有效期为1年,咱们能够申请两个 PP 文件,相隔半年,差很少到时间发新版时就换个新 PP 文件。

更多能够看iOS 各类证书的做用、有效期、过时的后果和解决办法

重签名

正常的打包流程就再也不说了。iOS完整的证书申请和打包过程

对 ipa 包进行修改后,因为摘要变了,因此验证会不经过。咱们能够采用重签名达到验证的效果。经常使用于逆向别人的 App,微信多开等途径。

App 的大体结构

打包出来 ipa 后,咱们解压能够看到大体结构。

image.png

  • 资源文件:例如图片、html等等

  • CodeSignature/CodeResources:这是一个 plist 文件,可用文本查看,其中的内容就是程序包(不包括Frameworks)全部文件的签名。意味着你的程序一旦签名,就不能更改其中任何文件。

  • 可执行文件:此文件跟资源文件同样须要签名。

  • mobileprovision:校验证书文件、Bundle ID。

  • Frameworks:程序引用的系统自带的Frameworks,每一个Frameworks其实就是一个 app,也包含签名信息。

iOS 系统验证签名有效性的过程

  1. 解压ipa

  2. 取出 embedded.mobileprovision,校验是否被篡改过

  3. 校验全部文件的签名

  4. 验证设备是否符合embedded.mobileprovision 的信息

  5. 对比 Info.plist 的 Bundle Id 是否符合 embedded.mobileprovision  文件中的信息

重签名的原理

既然签名是由证书mobileprovision共同实现,那么重签名的过程其实就是将新的证书mobileprovision替换旧文件的过程,但因为系统在验证app是否合法的时候还会随机验证受权设备列表和Bundle ID、因此必须修改Bundle ID新的mobileprovision中的信息保持一致,不然将会有验证失败的风险。

重签名的尝试

笔者以前打的是企业包,针对不一样客户要实现不一样 App Icon 和 App name等。若是一个一个打,一个打7分钟。💩

利用重签名,能够快速替换 ipa 中的内容,实现装逼的效果。

步骤以下

  1. 打包出一份 ipa。

  2. 修改 ipa 内对应文件。此时摘要变化了,至关于签名失效,苹果校验时就知道该 app 被篡改 了。

  3. 重签名

  • 3.1 删除插件
  • 3.2 对FrameWorks进行签名
  • 3.3 给可执行文件执行权限
  • 3.4 拷贝描述文件
  • 3.5 修改info.plist中的Bundle ID
  • 3.6 生成plist权限文件
  • 3.7 签名整个APP
  • 3.8 生成ipa包

具体实现,更多可查看以前写过的一篇文章 iOS —— 两套自动打包脚本

参考

相关文章
相关标签/搜索