借腾讯开源 VasDolly,谈谈 Android 签名和多渠道打包的原理!


2.1 应用签名

通过对 Apk 进行签名,开发者可以证明对 Apk 的所有权和控制权,可用于安装和更新其应用。而在 Android 设备上的安装 Apk ,如果是一个没有被签名的 Apk,则会被拒绝安装。

在安装 Apk 的时候,软件包管理器也会验证 Apk 是否已经被正确签名,并且通过签名证书和数据摘要验证是否合法没有被篡改。只有确认安全无篡改的情况下,才允许安装在设备上。

简单来说,APK 的签名主要作用有两个:

  1. 证明 APK 的所有者。
  2. 允许 Android 市场和设备校验 APK 的正确性。

而在 Android 中,支持两种应用签名的方案:

  1. 基于 JAR 签名方案(v1 方案)。
  2. Android Nougat(7.0) 中引入的 APK 签名方案 v2(v2 方案)。

既然签名方案在升级,v1 方案一定有一些缺陷的地方,接下来我们先来了解一下这两个方案的细节。

2.2 v1 签名方案

v1 签名方案,并不会保护 Apk 内的所有内容,有一些例外部分,被修改也并不会导致签名失效。例如:ZIP 元数据。

这样,在验证 APK 签名的时候,就需要处理大量不可信(尚未经过验证)的数据结构,然后还需要过滤并舍弃掉这部分不受签名保护的数据,再进行签名校验。也就是说你可以在已签名的文件中,增加一些不被签名保护的内容,这将导致受攻击的可能增大。

另外,v1 方案是对 APK 内部的被保护的原始文件(未压缩),单独进行计算数据摘要,所以在验证期间,也需要对每个文件进行减压再进行签名校验,来验证是否被篡改。所以在验证 APK 签名的时候,必须解压 APK 的所有已压缩的文件条目进行数据摘要的校验,而这些,都将需要花费更多的时间和内存。

正是因为 v1 方案的缺陷,Android 7.0 开始,才引入了 APK 签名方案 v2。

2.3 v2 签名方案

APK 签名方案 v2 是一种全文件的签名方案,该方案能够对 APK 所有受保护的部分进行签名保护,从能能够发现它们被篡改。

在 APK 验证期间,v2 方案会将 APK 文件视为 Blob,并对整个文件进行签名检查。对 APK 进行的任何修改(包括对 ZIP 元数据的修改),都会使 APK 签名作废。

使用 APK 签名方案 v2 进行签名时,会在 APK 文件中,插入一个 APK 签名块,该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名分块”内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。

该分块包含多个 “ID-值” 对,所采用的封装方式有助于更轻松地在 APK 中找到该分块。APK 的 v2 签名会存储为一个 “ID-值” 对,其中 ID 为 0x7109871a

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上图是签名前后,APK 文件结构的对比。可以看到在 v2 已签名的 APK 中,包含了 4 个部分。

  1. ZIP 条目的内容。
  2. APK 签名分块(APK Signing Block)。
  3. ZIP 中央目录。
  4. ZIP 中央目录结尾。

APK 签名方案 v2 负责保护第 1、3、4 部分的完整性,以及第 2 部分包含的 APK 签名方案 v2 分块中的 signed data 分块的完整性。

第 1、3 和 4 部分的完整性通过其内容的一个或多个摘要来保护,这些摘要存储在 signed data 分块中,而这些分块则通过一个或多个签名来保护。

第 1、3 和 4 部分的摘要信息,采用一种类似两级 Merkle 树的方式进行计算,所以效率上会提高很多。这个就比较复杂了,大家有兴趣再深入研究。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

既然已经有了 v2 方案,我们是否可以完全舍弃 v1 方案,只使用 v2 方案呢?

从官方文档了解到,因为 APK 签名方案 v2 是在 Android 7.0 中引入的,为了使 APK 可以在 Android 6.0 以及更低的版本中正常安装,应该先使用 JAR签名(v1 签名)对 APK 进行签名然后再使用 v2 方案对其进行签名

而在实际测试中,这种仅使用 v2 方案不使用 v1 方案的情况,是可以编译通过的,并且在 Android 7.0 之上的设备上也是可以安装和运行,但是在 7.0 之下,因为不检测 v2 签名,而 APK 又不存在 v1 签名,在安装的时候,会提示没有签名的错误。

为了保证兼容性的问题,在 7.0 以上的设备中,也是兼容了 v1 签名的方案。所以 v2 签名方案,暂时并不是一个强制的方案。

优先级是:优先校验 v2 方案,没有或者不存在校验机制,则校验 v1 方案

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.4 两种方案对比

到这里,我想应该对 v1 和 v2 签名方案应该已经有一定了解了。v2 签名既然是升级版,就是为了解决 v1 签名方案的一些问题。

1、效率问题

v1 方案,会在 /META-INF/MANIFEST.MF 文件中,记录所有需要校验签名的文件的数据摘要,并且这里生产数据摘要是依据压缩前的源文件,而在打包的过程中,这些文件又会被压缩。

所以在验证签名的过程中,需要先解压出原始文件,才能计算数据摘要从而验证它,而这个过程,会消耗更多的时间和内存。

v2 签名方案,是对 APK 文件本身进行数据摘要计算,也就是说它只计算一个文件(v1 会计算 Apk 内的很多文件),这样就不存在解压 APK 的操作,效率和内存都得到优化。

2、安全问题

v1 方案,它只会对 APK 内部,部分文件进行校验,并不会对 APK 的完整性进行校验。因此,签名后,我们依然可以修改 APK 文件,例如:美团的多渠道方案就是在 /META-INF/ 目录下,添加一个空文件,使用文件名来标志渠道。

而 v2 签名是针对整个 APK 进行校验,所以对 APK 的任何改动,都无法通过 v2 签名的验证,这样安全性会更高。

关于签名校验的耗时上,主要影响的是安装耗时,这里有一份实验室数据(Nexus 6P、Android 7.1.1)可供参考。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

差不多 2.x 倍的差距,v2 签名对 APK 的安装还是有不少提升的。

三、常见的多渠道方案

多渠道的需求点,在于同一个 App,需要有一些不同来区分它们,最常见的场景就是 Android 国内的市场,对不同的市场使用不同的渠道包,它们的代码是一致的,只是一个渠道号的数据不一样。这样区分的好处在于数据更清晰,我们知道那个渠道的用户是优质用户。

3.1 被废弃的方案

既然签名方案在升级,多渠道的方案也需要升级。曾经有一写可行的方案,基本上已经被废弃了。例如:Gradle Plugin 配置不同的 Flavors、利用 ApkTool 解包改数据再重新打包并重新签名。

这些方案都有一些局限性。例如 Gradle Flavors 方案,每个渠道都需要重新打包,非常的耗时,并且生成的渠道包 DEX 的 CRC 值都不一致,不利于我们使用热更新的方案;而 ApkTool 的方案,首先 解包→打包→重新签名 的过程同样耗时,其次在于,不稳定,可能升级了 Gradle Plugin 的版本之后,会导致解包失败。

所以我们在想,一个高效的多渠道打包方案,有几个关键单需要注意。

  1. 不能破坏签名。
  2. 不能重新打包。
  3. 读取信息,必须高效。

不破坏签名就限制了不能解包以及重新签名,势必对效率有所提高。

而除了 VasDolly 之外,市面上流传比较广的就是 美团 给出的 Walle 方案,这里就以它们的原理进行简单的讲解。

3.2 v1 签名下的常见多渠道方案

v1 下对签名的校验比较弱了,美团给出了完整的解决方案。前面也介绍过,就是在以及打包签名好的 Apk 中,向 /META-INF 目录下,写入一个空文件,以文件名来标识渠道号。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,使用这样的方案,并不会破坏 v1 签名,所以效率会很高。

而在腾讯的 VasDolly 中,其实是向 Apk 文件的 EOCD 部分,增加渠道的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

APK 文件本质上是一个 ZIP 包,而 EOCD 就是上图所示的第三部分,并且这部分是不被 v1 签名校验的,可以用来记录我们的渠道信息。

3.3 v2 签名下的多渠道方案

v2 方案下,其实腾讯 VasDolly 和美团的 Walle 方案,并没有什么区别,因为验证更强了,大家可操作的区域就只有那么多了。

前面也提到过,使用 v2 签名后的 APK 文件结构中,插入了一个 APK Signing Block 的签名块。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值