新一代开源Android渠道包生成工具Walle

在Android 7.0(Nougat)推出了新的应用签名方案APK Signature Scheme v2后,之前快速生成渠道包的方式(美团Android自动化之旅—生成渠道包)已经行不通了,在此应用签名方案下如何快速生成渠道包呢?

本文会对新的应用签名方案APK Signature Scheme v2以及新一代渠道生成工具进行详细深入的介绍。

新的应用签名方案APK Signature Scheme v2

Android 7.0(Nougat)引入一项新的应用签名方案APK Signature Scheme v2,它是一个对全文件进行签名的方案,能提供更快的应用安装时间、对未授权APK文件的更改提供更多保护,在默认情况下,Android Gradle 2.2.0插件会使用APK Signature Scheme v2和传统签名方案来签署你的应用。

下面以 新的应用签名方案 来指APK Signature Scheme v2。

目前该方案不是强制性的,在 build.gradle 添加 v2SigningEnabled false ,就能使用传统签名方案来签署我们的应用(见下面的代码片段)。

  android {...defaultConfig { ... }signingConfigs {release {storeFile file("myreleasekey.keystore")storePassword "password"keyAlias "MyReleaseKey"keyPassword "password"v2SigningEnabled false}}}

但新的应用签名方案有着良好的向后兼容性,能完全兼容低于Android 7.0(Nougat)的版本。对比旧签名方案,它有更快的验证速度和更安全的保护,因此新的应用签名方案可能会被采纳成一个强制配置,笔者认为现在有必要对现有的渠道包生成方式进行检查、升级或改造来支持新的应用签名方案。

新的签名方案对已有的渠道生成方案有什么影响呢?下图是新的应用签名方案和旧的签名方案的一个对比:

新的签名方案会在ZIP文件格式的 Central Directory 区块所在文件位置的前面添加一个APK Signing Block区块,下面按照ZIP文件的格式来分析新应用签名方案签名后的APK包。

整个APK(ZIP文件格式)会被分为以下四个区块: 1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block) 2. APK Signing Block 3. ZIP Central Directory 4. ZIP End of Central Directory

新应用签名方案的签名信息会被保存在区块2(APK Signing Block)中, 而区块1(Contents of ZIP entries)、区块3(ZIP Central Directory)、区块4(ZIP End of Central Directory)是受保护的,在签名后任何对区块1、3、4的修改都逃不过新的应用签名方案的检查。

之前的渠道包生成方案是通过在META-INF目录下添加空文件,用空文件的名称来作为渠道的唯一标识,之前在META-INF下添加文件是不需要重新签名应用的,这样会节省不少打包的时间,从而提高打渠道包的速度。但在新的应用签名方案下META-INF已经被列入了保护区了,向META-INF添加空文件的方案会对区块1、3、4都会有影响,新应用签名方案签署的应用经过我们旧的生成渠道包方案处理后,在安装时会报以下错误:

Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: 
Failed to collect certificates from base.apk: META-INF/CERT.SF indicates base.apk is signed using APK Signature Scheme v2, 
but no such signature was found. Signature stripped?]

目前另外一种比较流行的渠道包快速生成方案(往APK中添加ZIP Comment)也因为上述原因,无法在新的应用签名方案下进行正常工作。

如果新的应用签名方案后续改成强制要求,那我们现有的生成渠道包的方式就会无法工作,那我们难道要退回到解放前,通过传统的方式(例如:使用APKTool逆向工具、采用Flavor + BuildType等比较耗时的方案来进行渠道包打包)来生成支持新应用签名方案的渠道包吗?

如果只有少量渠道包的场景下,这种耗时时长还能够勉强接受。但是目前我们有将近900个渠道,如果采用传统方式打完所有的渠道包需要近3个小时,这是不能接受的。

那我们有没有其他更好的渠道包生成方式,既能支持新的应用签名方案,又能体验毫秒级的打包耗时呢?我们来分析一下新方案中的区块2——Block。

可扩展的APK Signature Scheme v2 Block

通过上面的描述,可以看出因为APK包的区块1、3、4都是受保护的,任何修改在签名后对它们的修改,都会在安装过程中被签名校验检测失败,而区块2(APK Signing Block)是不受签名校验规则保护的,那是否可以在这个不受签名保护的区块2(APK Signing Block)上做文章呢?我们先来看看对区块2格式的描述:

偏移字节数描述
@+08这个Block的长度(本字段的长度不计算在内)
@+8n一组ID-value
@-248这个Block的长度(和第一个字段一样值)
@-1616魔数 “APK Sig Block 42”

区块2中APK Signing Block是由这几部分组成:2个用来标示这个区块长度的8字节 + 这个区块的魔数(APK Sig Block 42)+ 这个区块所承载的数据(ID-value)。

我们重点来看一下这个ID-value,它由一个8字节的长度标示+4字节的ID+它的负载组成。V2的签名信息是以ID(0x7109871a)的ID-value来保存在这个区块中,不知大家有没有注意这是一组ID-value,也就是说它是可以有若干个这样的ID-value来组成,那我们是不是可以在这里做一些文章呢?

为了验证我们的想法,先来看看新的应用签名方案是怎么验证签名信息的,见下图:

通过上图可以看出新的应用签名方案的验证过程: 1. 寻找APK Signing Block,如果能够找到,则进行验证,验证成功则继续进行安装,如果失败了则终止安装 2. 如果未找到APK Signing Block,则执行原来的签名验证机制,也是验证成功则继续进行安装,如果失败了则终止安装

那Android应用在安装时新的应用签名方案是怎么进行校验的呢?笔者通过翻阅Android相关部分的源码,发现下面代码段是用来处理上面所说的ID-value的:

    public static ByteBuffer findApkSignatureSchemeV2Block(ByteBuffer apkSigningBlock,Result result) throws SignatureNotFoundException {checkByteOrderLittleEndian(apkSigningBlock);// FORMAT:// OFFSET       DATA TYPE  DESCRIPTION// * @+0  bytes uint64:    size in bytes (excluding this field)// * @+8  bytes pairs// * @-24 bytes uint64:    size in bytes (same as the one above)// * @-16 bytes uint128:   magicByteBuffer pairs = sliceFromTo(apkSigningBlock, 8, apkSigningBlock.capacity() - 24);int entryCount = 0;while (pairs.hasRemaining()) {entryCount++;if (pairs.remaining() < 8) {throw new SignatureNotFoundException("Insufficient data to read size of APK Signing Block entry #" + entryCount);}long lenLong = pairs.getLong();if ((lenLong < 4) || (lenLong > Integer.MAX_VALUE)) {throw new SignatureNotFoundException("APK Signing Block entry #" + entryCount+ " size out of range: " + lenLong);}int len = (int) lenLong;int nextEntryPos = pairs.position() + len;if (len > pairs.remaining()) {throw new SignatureNotFoundException("APK Signing Block entry #" + entryCount + " size out of range: " + len+ ", available: " + pairs.remaining());}int id = pairs.getInt();if (id == APK_SIGNATURE_SCHEME_V2_BLOCK_ID) {return getByteBuffer(pairs, len - 4);}result.addWarning(Issue.APK_SIG_BLOCK_UNKNOWN_ENTRY_ID, id);pairs.position(nextEntryPos);}throw new SignatureNotFoundException("No APK Signature Scheme v2 block in APK Signing Block");}

上述代码中关键的一个位置是 if (id == APK_SIGNATURE_SCHEME_V2_BLOCK_ID) {return getByteBuffer(pairs, len - 4);},通过源代码可以看出Android是通过查找ID为 APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a 的ID-value,来获取APK Signature Scheme v2 Block,对这个区块中其他的ID-value选择了忽略。

在APK Signature Scheme v2中没有看到对无法识别的ID,有相关处理的介绍。

当看到这里时,我们可不可以设想一下,提供一个自定义的ID-value并写入该区域,从而为快速生成渠道包服务呢?

怎么向ID-value中添加信息呢?通过阅读ZIP的文件格式和APK Signing Block格式的描述,笔者通过编写下面的代码片段进行验证,发现通过在已经被新的应用签名方案签名后的APK中添加自定义的ID-value,是不需要再次经过签名就能安装的,下面是部分代码片段。

  public void writeApkSigningBlock(DataOutput dataOutput) {long length = 24;for (int index = 0; index < payloads.size(); ++index) {ApkSigningPayload payload = payloads.get(index);byte[] bytes = payload.getByteBuffer();length += 12 + bytes.length;}ByteBuffer byteBuffer = ByteBuffer.allocate(Long.BYTES);byteBuffer.order(ByteOrder.LITTLE_ENDIAN);byteBuffer.putLong(length);dataOutput.write(byteBuffer.array());for (int index = 0; index < payloads.size(); ++index) {ApkSigningPayload payload = payloads.get(index);byte[] bytes = payload.getByteBuffer();byteBuffer = ByteBuffer.allocate(Integer.BYTES);byteBuffer.order(ByteOrder.LITTLE_ENDIAN);byteBuffer.putInt(payload.getId());dataOutput.write(byteBuffer.array());dataOutput.write(bytes);}...}

新一代渠道包生成工具

到这里为止一个新的渠道包生成方案逐步清晰了起来,下面是新一代渠道包生成工具的描述:

  1. 对新的应用签名方案生成的APK包中的ID-value进行扩展,提供自定义ID-value(渠道信息),并保存在APK中
  2. 而APK在安装过程中进行的签名校验,是忽略我们添加的这个ID-value的,这样就能正常安装了
  3. 在App运行阶段,可以通过ZIP的EOCD(End of central directory)Central directory等结构中的信息(会涉及ZIP格式的相关知识,这里不做展开描述)找到我们自己添加的ID-value,从而实现获取渠道信息的功能

新一代渠道包生成工具完全是基于ZIP文件格式和APK Signing Block存储格式而构建,基于文件的二进制流进行处理,有着良好的处理速度和兼容性,能够满足不同的语言编写的要求,目前笔者采用的是Java+Groovy开发, 该工具主要有四部分组成: 1. 用于写入ID-value信息的Java类库 2. Gradle构建插件用来和Android的打包流程进行结合 3. 用于读取ID-value信息的Java类库 4. 用于供com.android.application使用的读取渠道信息的AAR

这样,每打一个渠道包只需复制一个APK,然后在APK中添加一个ID-value即可,这种打包方式速度非常快,对一个30M大小的APK包只需要100多毫秒(包含文件复制时间)就能生成一个渠道包,而在运行时获取渠道信息只需要大约几毫秒的时间。

这个项目我们取名为Walle(瓦力),已经开源,项目的Github地址是: https://github.com/Meituan-Dianping/walle (求Issue、PR、Star)。希望业内有类似需求的团队能够在APK Signature Scheme V2签名下愉快地生成渠道包,同时也期待大家一起对该项目进行完善和优化。

总结

以上就是我们对新的应用签名方案进行的分析,并根据它所带来的文件存储格式上的变化,找到了可以利用的ID-value,然后基于这个ID-value来构建我们新一代渠道包生成工具。

新一代渠道包生成工具能够满足新应用签名方案对安全性的要求,同时也能满足对渠道包打包时间的要求,至此大家生成渠道包的方式需要升级了!

文章中引用的图片来源于:https://source.android.com/security/apksigning/v2.html

参考文献

  1. APK Signature Scheme v2
  2. ApkSigner的源代码
  3. apksig的源代码
  4. [ZIP Format](https://en.wikipedia.org/wiki/Zip_(file_format)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/478267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

领域应用 | 机器知道哪吒是部电影吗?解读阿里巴巴概念图谱AliCG

转载公众号 | PaperWeekly概念是人类认知世界的基石。比如对于“哪吒好看吗&#xff1f;”&#xff0c;“哪吒铭文搭配建议”两句话&#xff0c;人可以结合概念知识理解第一个哪吒是一部电影&#xff0c;第二个哪吒是王者荣耀的英雄。然而机器能理解吗&#xff1f;针对这一问题…

LeetCode 605. 种花问题

1. 题目 假设你有一个很长的花坛&#xff0c;一部分地块种植了花&#xff0c;另一部分却没有。可是&#xff0c;花卉不能种植在相邻的地块上&#xff0c;它们会争夺水源&#xff0c;两者都会死去。 给定一个花坛&#xff08;表示为一个数组包含0和1&#xff0c;其中0表示没种…

美团点评业务风控系统构建经验

本文根据“第八届中国系统架构师大会”演讲内容整理而成。 美团最初以团购的形式出现&#xff0c;到现在有了很大的业务形态转变。尤其是经过与大众点评的业务融合&#xff0c;从单一业务发展成了覆盖到店餐饮、到店综合、猫眼、外卖、酒店、旅游等多个垂直领域的综合性电商&am…

95后程序员晒出工资单:狠补了这个,真香…

作为AI 初学者来说&#xff0c;最大的问题就是&#xff1a;资料太多&#xff01;&#xff01;&#xff01;看不完&#xff01;&#xff01;&#xff01;不知道如何取舍&#xff01;&#xff01;&#xff01;人的精力有限&#xff01;&#xff01;&#xff01;大部分想转行AI算法…

领域应用 | 小米在知识表示学习的探索与实践

转载公众号 | DataFunTalk导读&#xff1a;知识表示是知识获取与应用的基础&#xff0c;贯穿了小米知识图谱的构建与应用。本文将结合小米知识图谱的构建及小爱问答场景&#xff0c;介绍融合文本和知识图谱的知识表示学习方法&#xff0c;以及知识表示在知识图谱补全、实体链接…

LeetCode 563. 二叉树的坡度(DFS)

1. 题目 给定一个二叉树&#xff0c;计算整个树的坡度。 一个树的节点的坡度定义即为&#xff0c;该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。 整个树的坡度就是其所有节点的坡度之和。 示例:输入: 1/ \2 3输出: 1 解释: 结点的坡度 …

多模态为什么比单模态好?第一份严谨证明来了!

文 | 橙橙子面试官: 听说你对多模态感兴趣&#xff0c;请问为什么多模态学习要比单模态学习效果好&#xff1f;候选人: 直观地&#xff0c;多模态学习可以聚合多源数据的信息&#xff0c;使得模型学习到的表示更加完备。以视频分类为例&#xff0c;同时使用字幕标题等文本信息、…

推荐:26种NLP练手项目(代码+数据)

1.分词 Word Segmentation chqiwang/convseg &#xff0c;基于CNN做中文分词&#xff0c;提供数据和代码。 对应的论文Convolutional Neural Network with Word Embeddings for Chinese Word Segmentation IJCNLP2017. 2.词预测 Word Prediction Kyubyong/word_prediction &…

会议交流 | 最新NLP核心技术与前沿实践分享!

2021年7月10日&#xff0c;09:00-18:10&#xff0c;DataFunSummit&#xff1a;自然语言处理峰会将如约而至&#xff0c;本次峰会由3位主席和6位出品人精心策划而来&#xff0c;邀请来自业界的40余位嘉宾从NLP基础技术、语义表示与计算、多模理解与生成、信息抽取与检索、人机对…

LeetCode 504. 七进制数(进制转换)

1. 题目 给定一个整数&#xff0c;将其转化为7进制&#xff0c;并以字符串形式输出。 示例 1: 输入: 100 输出: "202"示例 2: 输入: -7 输出: "-10" 注意: 输入范围是 [-1e7, 1e7] 。来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xf…

领域应用 | 常识性概念图谱建设以及在美团场景中的应用

转载公众号 | 美团技术团队常识性概念图谱&#xff0c;是围绕常识性概念建立的实体以及实体之间的关系&#xff0c;同时侧重美团的场景构建的一类知识图谱。本文介绍了美团常识性概念图谱构建的Schema&#xff0c;图谱建设中遇到的挑战以及建设过程中的算法实践&#xff0c;最后…

美团数据库中间件DBProxy开源

随着数据量的不断增大&#xff0c;传统的直连数据库对数据进行访问的方式已经无法满足一般公司的需求。通过数据库中间件&#xff0c;可以对数据库进行水平扩展&#xff0c;由原来单台数据库扩展到多台数据库&#xff0c;数据库中间件通过路由规则将数据的访问请求路由到其中一…

不卷学术了,这次卷一波NLP实战落地经验

作为最典型的 AI 领域之一&#xff0c;NLP 这些年也是越来越热门&#xff0c;基本上是各大厂必备了。随着 OpenAI 等技术的诞生、迁移学习等技术的成功应用&#xff0c;使得 NLP 技术在搜索、推荐、信息流、互联网金融、社交网络等领域不断发展壮大。与此同时&#xff0c;NLP 工…

docker挂载文件躺过的坑

Docker 实现挂载的三种方式 docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused “exec: “-v”: executable file not found in $PATH”: unknown. 看着启动成功了&#xff0c;但查日志启动失败 日…

美团团购订单系统优化记

团购订单系统简介 美团团购订单系统主要作用是支撑美团的团购业务&#xff0c;为上亿美团用户购买、消费提供服务保障。2015年初时&#xff0c;日订单量约400万~500万&#xff0c;同年七夕订单量达到800万。 目标 作为线上S级服务&#xff0c;稳定性的提升是我们不断的追求。尤…

论文浅尝 | emrKBQA: 一个面向临床医疗问答的KBQA数据集

笔记整理 | 谭亦鸣&#xff0c;东南大学博士生来源&#xff1a;BioNLP ’21 workshop, ACL ‘21链接&#xff1a;https://www.aclweb.org/anthology/2021.bionlp-1.7.pdf论文主要包含两个部分的核心工作&#xff1a;emrKBQA数据集&#xff0c;对应的benchmark。基于MIMIC-III …

Fine-tune之后的NLP新范式:Prompt越来越火,CMU华人博士后出了篇综述文章

文 | 刘鹏飞源 | 机器之心CMU 博士后研究员刘鹏飞&#xff1a;近代自然语言处理技术发展的第四范式可能是预训练语言模型加持下的 Prompt Learning。近几年&#xff0c;NLP 技术发展迅猛&#xff0c;特别是 BERT 的出现&#xff0c;开启了 NLP 领域新一轮的发展。从 BERT 开始&…

会议交流 | 世界人工智能大会“大数据关联”论坛举行

转载公众号 | 创邻科技2021年7月8日&#xff0c;由世界人工智能大会组委会与浙江创邻科技有限公司共同筹办的“大数据关联时代下的图数据库技术与应用论坛”在上海世博中心圆满落幕。论坛邀请了清华大学、北京大学、复旦大学、浙江大学、天津大学等多位学术届的思想领袖和工商银…

LeetCode 994. 腐烂的橘子(图的BFS)

1. 题目 在给定的网格中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b; 值 1 代表新鲜橘子&#xff1b; 值 2 代表腐烂的橘子。 每分钟&#xff0c;任何与腐烂的橘子&#xff08;在 4 个正方向上&#xff09;相邻的新鲜橘子都会腐烂…

美团酒店直连产品数据一致性演进

美团酒店直连项目自2013年末开始&#xff0c;通过业务上的不断完善和技术上的不断改进&#xff0c;至今已经接入200多家供应商&#xff0c;其中在线酒店3万以上&#xff0c;在线SPU30万以上。经过两年的成长&#xff0c;美团酒店直连平台终于在2015年末发展为国内最大的酒店直连…