校验过程:在安装步骤校验:
1.检查APK中所有的文件,对应的摘要值和MANIFEST.MF中的值保持一致
2.对MANIFEST.MF中的值做二次摘要,查看是否和CERT.SF中的值保持一致
3.使用数字证书文件CERT.RSA检查SF文件有没被修改过,使用公钥证书解密
4.解密后的摘要信息和步骤2中的二次摘要信息对比,看下是否一致
5.一致就通过,说明apk信息没有被更改过
为什么使用这样的签名流程呢?
1.更改APK文件里面的文件,MANIFEST.MF中的摘要信息不一致,校验失败
2.在1的基础上更改MANIFEST.MF的摘要信息,那么和CERT.SF中的摘要信息会不一致,校验失败
3.在2的基础上更改CERT.SF中的摘要信息,那么CERT.RSA中的签名信息不一致,校验失败。
4.在3的基础上更改证书,不行,因为没有私钥。
所有可以基本上保证数据的不可篡改性
v2签名:v1缺点:
- 签名速度慢,需要对每个文件进行签名
- 完整性保持不够:因为META-INF 目录用于签名,所以不会记录到校验信息内,用户可以在这个文件中随意添加文件
v2签名:
就是把 APK 按照 1M 大小分割,分别计算这些分段的摘要,最后把这些分段的摘要在进行计算得到最终的摘要也就是 APK 的摘要。然后将 APK 的摘要 数字证书 其他属性生成签名数据写入到 APK Signing Block 区块。
v2校验:
v2 签名机制是在 Android 7.0 以及以上版本才支持。因此对于 Android 7.0 以及以上版本,在安装过程中,如果发现有 v2 签名块,则必须走 v2 签名机制,不能绕过。否则降级走 v1 签名机制。v1 和 v2 签名机制是可以同时存在的,其中对于 v1 和 v2 版本同时存在的时候,v1 版本的 META_INF 的 .SF 文件属性当中有一个 X-Android-APK-Signed 属性:X-Android-APK-Signed: 2
v2 对多渠道打包的影响
之前的渠道包生成方案是通过在 META-INF 目录下添加空文件,用空文件的名称来作为渠道的唯一标识。但在新的应用签名方案下 META-INF 已经被列入了保护区了,向 META-INF 添加空文件的方案会对区块 1、3、4 都会有影响。
总结V2:
- 1.V2并行计算加快签名速度
- 2.V2保证META-INFO目录不会被篡改
- 1.复制APK到/data/app目录下。解压并扫描包
- 2.资源管理器解析apk里面的资源文件
- 3.解析AndroidManifest文件,并在/data/data/目录下创建对应的应用数据目录
- 4.然后对dex文件进行优化,并保存在dalvik-cache目录下。
- 5.将AndroidManifest文件解析出的四大组件信息注册到PackageManagerService中
- 6.安装完成后,发送广播。
CI 即 持续集成,在大型开发团队中,CI 的建设是重中之重,CI 主要包括 打包构建、Code Review、代码工程管理、代码扫描 等一系列流程。它的 整套运转体系 可以简化为下图:
1、持续集成的原因构建 CI 的目的主要是为了解决以下四个问题。
1)、项目依赖复杂随着业务的发展,基础组件库的数量会持续上涨,这个时候组件间的关系就会变得错综复杂,这将会导致如下 两个问题:
- 1、如果某个开发同学需要修改代码,极有可能会影响到其它业务,牵一发而动全身。
- 2、人工维护组件间复杂的依赖关系非常困难。
在日常的功能开发中,我们一般都会经 代码开发、组件发版、组件集成、打包、测试这五个步骤。如果测试发现 Bug 需要进行修复,然后会再次经历代码修改、组件发版、组件集成、打包、测试,直到测试通过交付产品。传统的研发流程如下图所示:
可以看到,开发同学在整个开发流程中需要手动提交 MR、升级组件、触发打包以及去实时监控流程的状态,这样肯定会严重影响开发的专注度,降低研发的生产力。
3)、与 App 性能监控体系的融合随着 App从 项目初期 => 成长期 => 成熟期,对性能的要求会越来越高,为了保障性能的足够稳定,我们需要制造出许多性能监控的工具,以实时监控我们应用的性能。而 App 性能监控体系必须和 CI 结合起来,以实现流程的自动化和平台化。
4)、项目的编译构建速度缓慢随着 App 的体积变大,依赖变多,项目的编译构建速度会越来越慢,缓慢的编译速度会严重拖垮开发同学的研发效率。因此,提升 App 的编译构建速度刻不容缓。
2、持续集成的主要步骤持续集成涉及的流程非常多,但是有 两个主要的步骤是非常重要 的,具体如下所示:
1)、代码检查为了防止不符合规范的代码提交到远程仓库中,我们需要 自定义一套符合自身项目的编码规范,并使用专门的插件来检测。自定义代码检测可以通过完全自己实现或者扩展 FindBugs 插件,例如美团就利用 Findbugs 实现了 Android 漏洞扫描工具 Code Arbiter,其中 FindBugs 是一个静态分析工具,它一般用来检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比来发现可能存在的问题,它可以以独立的 JAR 包形式运行,也可以作为集成开发工具的插件形式而存在。而 FindBugs 插件具有着极强的可扩展性,只需要将扩展的 JAR 包导入 FindBugs 插件,重启 AS,即可完成相关功能的扩展。
在 FindBugs 有一款专门对安全问题进行检测的扩展插件 Find Security Bugs,该插件主要用于对 Web 安全问题进行检测,也有极少对Android相关安全问题的检测规则。我们只需要 定制化自己的 Find Security Bugs,通过增加检测项来检测尽可能多的安全问题,通过优化检测规则来减少检测的误报 即可,这里我们可以直接使用 Android_Code_Arbiter 这个插件,它 去除了其中跟 Android 漏洞无关的漏洞,保留了与 Android 相关的,并增加了其它的一些检测项,以此形成了针对与于 Android 的源码审计工具。
此外,我们也可以使用 第三方的代码检查工具,例如收费的 Coverity,以及 Facebook 开源的 Infer。
然而,尽管将问题代码扫描出来了,可是还是会有不少开发同学不知道如何修改,对于这种情况,我们可以给在自定义代码扫描工具的时候,对于每一个问题检查项都给出对应的修改方针。
最后,我们可以据此建立一个解决项目异常的流程:建立一个服务专门每天跑项目的 Lint 检查,跑完将警告汇总分配到对应的负责人身上,并邮件告知他,直到上线。
2)、Code ReviewCode Review 非常重要,在每一次提交代码时,我们都需要自己进行一次 Code Review,然后再让别人去 Review,以建立自身良好的技术品牌。
有些同学可能会认为 CI 并不重要,它好像跟具体的技术并无关联。但是,我们需要知道,学会不仅仅是钻在开发角度看问题,跳脱出来,站在用户角度,站在产品角度,或许会有意外的收获。
总结在本篇文章,我们即涉及到了 Android 编译的深度方面:App 的编译和打包流程、签名算法的原理,也涉及到了 Android 编译的广度方面:持续集成。因此,在我们学习的过程中,技术就像是一棵树,在顶部叶子上各个领域看似毫不相干,但是在一个领域越往下深入,各个领域相互交错到的知识或者设计方式就越多,所以技术深度和广度并不是对立面,对技术深度的探索不仅有利于你在特定领域有更深理解,更加可以帮助你轻松切换到另一个领域,特别是像前端的各细分领域的工作,很多领域的知识背后都殊途同归,而技术的广度也不是有的人说的那样不堪,在有技术深度的基础上,去拓展自己的技术广度,其实会让你对原有技术的理解变得更加地深入。