Hi,你们好,我是承香墨影!html
当咱们须要发布一款 App 到应用市场的时候,通常须要咱们针对不一样的市场生产不一样的渠道包,它们使用的是同一套代码,只是会包含一些各自的渠道信息,用于咱们作数据分析。android
前几天,企鹅电竞团队开源了本身的 Android Apk 多渠道打包工具:VasDolly,比美团的 Walle 更全面一些。git
正好借这个机会,来说解一下 Android 的不一样版本的签名机制的差别。github
经过对 Apk 进行签名,开发者能够证实对 Apk 的全部权和控制权,可用于安装和更新其应用。而在 Android 设备上的安装 Apk ,若是是一个没有被签名的 Apk,则会被拒绝安装。c#
在安装 Apk 的时候,软件包管理器也会验证 Apk 是否已经被正确签名,而且经过签名证书和数据摘要验证是否合法没有被篡改。只有确认安全无篡改的状况下,才容许安装在设备上。安全
简单来讲,APK 的签名主要做用有两个:数据结构
而在 Android 中,支持两种应用签名的方案:工具
既然签名方案在升级,v1 方案必定有一些缺陷的地方,接下来咱们先来了解一下这两个方案的细节。学习
v1 签名方案,并不会保护 Apk 内的全部内容,有一些例外部分,被修改也并不会致使签名失效。例如:ZIP 元数据。测试
这样,在验证 APK 签名的时候,就须要处理大量不可信(还没有通过验证)的数据结构,而后还须要过滤并舍弃掉这部分不受签名保护的数据,再进行签名校验。也就是说你能够在已签名的文件中,增长一些不被签名保护的内容,这将致使受攻击的可能增大。
另外,v1 方案是对 APK 内部的被保护的原始文件(未压缩),单独进行计算数据摘要,因此在验证期间,也须要对每一个文件进行减压再进行签名校验,来验证是否被篡改。因此在验证 APK 签名的时候,必须解压 APK 的全部已压缩的文件条目进行数据摘要的校验,而这些,都将须要花费更多的时间和内存。
正是由于 v1 方案的缺陷,Android 7.0 开始,才引入了 APK 签名方案 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 个部分。
APK 签名方案 v2 负责保护第 一、三、4 部分的完整性,以及第 2 部分包含的 APK 签名方案 v2 分块中的 signed data
分块的完整性。
第 一、3 和 4 部分的完整性经过其内容的一个或多个摘要来保护,这些摘要存储在 signed data
分块中,而这些分块则经过一个或多个签名来保护。
第 一、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 方案。
到这里,我想应该对 v1 和 v2 签名方案应该已经有必定了解了。v2 签名既然是升级版,就是为了解决 v1 签名方案的一些问题。
一、效率问题
v1 方案,会在 /META-INF/MANIFEST.MF
文件中,记录全部须要校验签名的文件的数据摘要,而且这里生产数据摘要是依据压缩前的源文件,而在打包的过程当中,这些文件又会被压缩。
因此在验证签名的过程当中,须要先解压出原始文件,才能计算数据摘要从而验证它,而这个过程,会消耗更多的时间和内存。
v2 签名方案,是对 APK 文件自己进行数据摘要计算,也就是说它只计算一个文件(v1 会计算 Apk 内的不少文件),这样就不存在解压 APK 的操做,效率和内存都获得优化。
二、安全问题
v1 方案,它只会对 APK 内部,部分文件进行校验,并不会对 APK 的完整性进行校验。所以,签名后,咱们依然能够修改 APK 文件,例如:美团的多渠道方案就是在 /META-INF/
目录下,添加一个空文件,使用文件名来标志渠道。
而 v2 签名是针对整个 APK 进行校验,因此对 APK 的任何改动,都没法经过 v2 签名的验证,这样安全性会更高。
关于签名校验的耗时上,主要影响的是安装耗时,这里有一份实验室数据(Nexus 6P、Android 7.1.1)可供参考。
差很少 2.x 倍的差距,v2 签名对 APK 的安装仍是有很多提高的。
多渠道的需求点,在于同一个 App,须要有一些不一样来区分它们,最多见的场景就是 Android 国内的市场,对不一样的市场使用不一样的渠道包,它们的代码是一致的,只是一个渠道号的数据不同。这样区分的好处在于数据更清晰,咱们知道那个渠道的用户是优质用户。
既然签名方案在升级,多渠道的方案也须要升级。曾经有一写可行的方案,基本上已经被废弃了。例如:Gradle Plugin 配置不一样的 Flavors、利用 ApkTool 解包改数据再从新打包并从新签名。
这些方案都有一些局限性。例如 Gradle Flavors 方案,每一个渠道都须要从新打包,很是的耗时,而且生成的渠道包 DEX 的 CRC 值都不一致,不利于咱们使用热更新的方案;而 ApkTool 的方案,首先 解包→打包→从新签名 的过程一样耗时,其次在于,不稳定,可能升级了 Gradle Plugin 的版本以后,会致使解包失败。
因此咱们在想,一个高效的多渠道打包方案,有几个关键单须要注意。
不破坏签名就限制了不能解包以及从新签名,势必对效率有所提升。
而除了 VasDolly 以外,市面上流传比较广的就是 美团 给出的 Walle 方案,这里就以它们的原理进行简单的讲解。
v1 下对签名的校验比较弱了,美团给出了完整的解决方案。前面也介绍过,就是在以及打包签名好的 Apk 中,向 /META-INF
目录下,写入一个空文件,以文件名来标识渠道号。
首先,使用这样的方案,并不会破坏 v1 签名,因此效率会很高。
而在腾讯的 VasDolly 中,实际上是向 Apk 文件的 EOCD 部分,增长渠道的信息。
APK 文件本质上是一个 ZIP 包,而 EOCD 就是上图所示的第三部分,而且这部分是不被 v1 签名校验的,能够用来记录咱们的渠道信息。
v2 方案下,其实腾讯 VasDolly 和美团的 Walle 方案,并无什么区别,由于验证更强了,你们可操做的区域就只有那么多了。
前面也提到过,使用 v2 签名后的 APK 文件结构中,插入了一个 APK Signing Block 的签名块。
在这个 APK 文件结构下,只有 块2 ,也就是记录 APK v2 签名信息的区域,不是所有参与 v2 签名的校验,因此你们都在这部分作文章。
APK Signing Block 中包含了多个 "ID-值" 的键值对,而 v2 签名的信息,会记录在 ID 为 0x7109871a
中,而不会校验其余 ID 下的值。
所以,基于 v2 签名的多渠道方案就这样诞生了:在 APK 签名块中添加一个额外的 ID-值,用于记录渠道信息。
在 VasDolly 开源以前,市面上支持 v2 签名的多渠道打包方案,就属美团的 Walle 了,下面简单比对一下它们的优缺点。
具体你想使用哪一种方案,就看你的实际须要了。
美团 Walle Github 地址:
https://github.com/Meituan-Dianping/walle
Walle 扫码直达
腾讯 VasDolly Github 地址:
https://github.com/Tencent/VasDolly/
VasDolly 扫码直达
部分图片来源以及参考资料:
https://source.android.com/security/apksigning/v2
https://github.com/Tencent/VasDolly/wiki/VasDolly%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86
https://tech.meituan.com/mt-apk-packaging.html
今天在公众号后台回复成长『成长』,将会获得我整理的一些学习资料,也能回复『加群』,一块儿学习进步。
推荐阅读: