关于Apk签名版本的一次探究

  事情是这样的,有一天产品突然说,每次打渠道包都需要找技术,麻烦,有没有办法可以让运营自己完成这个事情。正好之前看过美团多渠道打包方案,有已经成功的例子在了,怕什么,话不多说开始撸。

  仿照着美团多渠道打包方案很快就撸完了,打包,安装,好使,不错不错,心情美滋滋,然而。。。

  交付测试适配。不久,测试反馈有部分手机不能安装,提示安装包未签名。WTF?没有签名??一脸懵逼,只有部分手机不能用,什么鬼。找了很多手机试了试,总算发现了点什么,所有Android系统7.0以上版本的手机不能用。确认了症状后,身为一个面向google程序员,自然一通搜索。。。

  应用签名资料都在这里了,主要就是一下几点:

1. Android 支持两种应用签名方案,一种是基于 JAR 签名的方案(v1 方案),另一种是 Android Nougat (Android 7.0) 中引入的 APK 签名方案 v2(v2 方案)。
2. Android 7.0 中引入了 APK 签名方案 v2(v2 方案)。该方案会对 APK 的内容进行哈希处理和签名,然后将生成的“APK 签名分块”插入到 APK 中。  
2. APK 签名方案 v2 是在 Android 7.0 (Nougat) 中引入的。为了使 APK 可在 Android 6.0 (Marshmallow) 及更低版本的设备上安装,应先使用 JAR 签名功能对 APK 进行签名,然后再使用 v2 方案对其进行签名。
3. 在 Android 7.0 中,可以根据 APK 签名方案 v2(v2 方案)或 JAR 签名(v1 方案)验证 APK。更低版本的平台会忽略 v2 签名,仅验证 v1 签名。

  总结,7.0以上的手机会首先验证v2签名,7.0以下的手机只验证v1签名。v2签名的安全性更强,之前人为的对apk的修改导致v2签名验证未通过。

  简单的处理这个问题,就是在代码中修改签名配置,去除v2签名,只使用v1签名。

1
2
3
4
5
6
7
8
9
signingConfigs {
config {
storeFile file("*.keystore")
storePassword "123456"
keyAlias "***"
keyPassword "123456"
v2SigningEnabled false
}
}

居安思危,思则有备,有备无患

  目前官方还提供有禁用v2签名的方法,万一那一天不提供禁用方法了,是不是就一夜回到解放前了,所以,还是要研究一下签名原理的,有备无患。

apk签名验证过程

  1. v1方案

    JAR 已签名的 APK 是一种标准的已签名 JAR,其中包含的条目必须与 META-INF/MANIFEST.MF 中列出的条目完全相同,并且所有条目都必须已由同一组签名者签名。

    1. 每个签名者均由一个包含 META-INF/.SF 和 META-INF/.(RSA|DSA|EC) 的 JAR 条目来表示。
    2. .(RSA|DSA|EC) 是具有 SignedData 结构的 PKCS #7 CMS ContentInfo,其签名通过 .SF 文件进行验证。
    3. .SF 文件包含 META-INF/MANIFEST.MF 的全文件摘要和 META-INF/MANIFEST.MF 各个部分的摘要。需要验证 MANIFEST.MF 的全文件摘要。如果该验证失败,则改为验证 MANIFEST.MF 各个部分的摘要。
    4. 对于每个受完整性保护的 JAR 条目,META-INF/MANIFEST.MF 都包含一个具有相应名称的部分,其中包含相应条目未压缩内容的摘要。所有这些摘要都需要验证。
    5. 如果 APK 包含未在 MANIFEST.MF 中列出且不属于 JAR 签名一部分的 JAR 条目,APK 验证将会失败。
  2. v2方案

    APK 签名方案 v2 是一种全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证。使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK 签名分块,该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名分块”内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。该模式在原有的签名模式上,增加校验APK的SHA256哈希值;这种新引入的签名机制,会对整个文件的每个字节都会做校验,包括 comment 区域。

    apk-before-after-signing

    使用v2签名,apk中包含四个部分:ZIP条目的内容、APK签名分块、ZIP中央目录、ZIP中央目录结尾。其中APK签名分块负责保护其余部分的完整性以及签名分块中的 singed data分块的完整性。


官方APK再签名或者校验签名工具apksigner介绍:
https://developer.android.com/studio/command-line/apksigner.html

检测工具下载地址:
https://github.com/bihe0832/AndroidAPKInfo/tree/master/CheckAndroidV2Signature.jar

v2多渠道快速打包方案:Walle:
https://tech.meituan.com/android-apk-v2-signature-scheme.html