目录

APK 签名

DakingTech 原创不易,转载请注明出处

APK 签名

APK 签名是 apk 文件摘要信息使用 keystore 中的私钥加密后的产物。

一旦内容被修改,摘要就会改变,签名也会失效。

如果 APK 签名跟其内容无法对应上,系统就会认为 apk 被篡改,从而拒绝安装,以保证系统的安全性。

目前 Android 有三种签名:V1、V2(Android 7+)、V3(Android 9+)。

V1 签名

/images/QQ20210427-135811@2x.png

  • MANIFEST.MF:记录 apk 中每一个文件名和对每个文件的摘要信息,主要作用是保证每个文件的完整性
  • CERT.SF:记录了对 MANIFEST.MF 文件整体的摘要信息以及每一块摘要的二次摘要信息,主要作用是保证 MANIFEST.MF 的完整性。
  • CERT.RSA:记录了 keystore 中存储的公钥证书信息以及对 CERT.SF 文件的签名信息(用 keystore 中的私钥进行签名),主要作用是保证来源。

使用的是 jarsigner,位于 <JDK 根目录>/bin/jarsigner

V1 签名过程为:

  1. 生成 MANIFEST.MF
  2. 生成 CERT.SF
  3. 利用 keystore 对 CERT.SF 进行签名,生成 CERT.RSA。

不同的 keystore 会生成不同的 CERT.RSA,而 MANIFEST.MF 和 CERT.SF 是不变的。

V1 签名存在的问题:

  • 校验速度慢:校验过程中需要对 apk 中所有文件进行摘要计算,当 apk 资源过多、性能较差的设备时,签名校验耗时较长,从而导致安装速度慢。
  • 完整性不足:V1 签名只会校验 apk 中的部分文件,例如 META-INF 文件夹就不会参与校验。

V2 签名

V2 签名是在 Android 7.0 时引入的,它解决了 V1 签名校验速度慢的问题,同时对 apk 完整性的校验扩展到整个安装包(包括META-INF 文件夹)。

使用的是 apkSigner,位于 <Android SDK 根目录>/build-tools/<API >= 24>/apksigner

V2 签名不针对单个文件进行摘要,而是针对 apk 进行分块摘要。

  1. 将 apk 分成多个 1M 体积的数据块
  2. 对每个数据块进行第一级摘要
  3. 对第一级摘要的集合进行第二级摘要

apk 安装时可以对第一级的分块摘要进行并行校验,大大提升了校验速度。

/images/2021-04-27-14-26-54.png

最后利用第二级摘要 + 数字证书 + 其他属性等信息来生成签名,并写入 APK Signing Block 中。

V2 签名前后的 apk 文件的组成对比如下:

/images/2021-04-27-14-42-00.jpg

其实,APK Signing Block 不是全部参与 V2 签名校验,只有其记录 apk 签名信息的部分参与校验。

V1 和 V2 签名可以同时存在于同一个 apk 中。对于 Android 7.0 及以上的设备,在安装过程中,如果发现 apk 有 V2 签名块,则必须走 V2 签名校验流程,否则降级走 V1 签名校验流程。而 Android 7.0 以下的设备,只能走 V1 签名校验流程。

Gradle 签名配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
android {
    ...

    signingConfigs {
        // BuildType 为 debug 时的签名配置
        debug {
            // debug 签名配置可以省略
            // 默认使用 Android Studio 内置的 debug keystore 进行签名,即~/.android/debug.keystore 文件
            ...
        }
        // BuildType 为 release 时的签名配置
        release {
            // keystore 相关配置
            storeFile file("<keystore 文件所在路径>")
            storePassword "<keystore 文件的密码>"
            keyAlias "<密钥的别名>"
            keyPassword "<密钥的密码>"
            // 开启 V1 签名
            v1SigningEnabled true
            // 开启 V2 签名
            v2SigningEnabled true
        }
    }
}

参考资料

移动端架构师-慕课网