我之前写了一篇 Android app 签名使用 keytool 工具的博客(原文地址: https://bin.zmide.com/?p=181

之前其实 Android 开发团队之前一直给 apk 使用的是 java 程序的签名方式。

我在这里再补上一个 keytool 说明的 oracle 官网链接: https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Signed_JAR_File

不过这种签名方式在 Android 7.0 开始改变,推出了属于 APK 的 v2 签名,在 Android 9.0 时还推出了 v3。似乎之后还会出 v4…

所以目前 Android 支持以下三种应用签名方案:

  • v1 方案:基于 JAR 签名。
  • v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)。
  • v3 方案:APK 签名方案 v3(在 Android 9 中引入)。

为了最大限度地提高兼容性,请按照 v1、v2、v3 的先后顺序采用所有方案对应用进行签名。与只通过 v1 方案签名的应用相比,还通过 v2+ 方案签名的应用能够更快速地安装到 Android 7.0 及更高版本的设备上。更低版本的 Android 平台会忽略 v2+ 签名,这就需要应用包含 v1 签名。

所以说,签名之间是互不影响的,也就是说可以不断叠加 buff ,现在 Android 团队推荐的是 v1 + v2 的签名方式(兼容 Android 6.0 以下和 Android 7.0 以上)目前的话 Android 10 是强制要求需要签名 v2 的 APP 才能安装了。

至于 v3 签名嘛,就是在 v2 签名的基础上增加了 APK 密钥轮替,也就是说解决了签名密钥丢失就不能更新 APP 的问题。但是安装 APP 的手机系统必须高于 Android 9.0,所以主流的 APK 签名方案目前都是: v1 + v2 签名

如果是单独的 v1 签名话,使用之前的 keytool 就可以实现了。但是想要 v2 签名的话就得用到我们今天的主角 apksigner 工具了。

apksigner 是 Android 开发团队推出的一个 apk 签名工具,可以签包含 v1,v2,v3,v4 的 APK 签名集合工具。

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

那么这个工具在哪里呢?我们知道在 Android 7.0 开始就推出了 v2 签名,所以在 android sdk 24 开始就带了这个工具。如果是使用 Android Studio 打包的话我们知道在 Generate Signed Bundle or APK 的时候选中上 Signature Versions 参数的 V1(Jar Signature)和 V2(Full APK Signature)选项就好了,如下图

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

但是如果我想给某个 APK 直接签名呢?那么我们就需要先找到 apksigner 工具的位置。首先我们得先找到我们 android sdk 的位置,打开 Android Studio 的设置页面就能看到我们下载 SDK 的文件夹了

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

我们打开这个文件夹,打开这个 build-tools 文件夹,这里面就是我们下载的各各版本的 android sdk 了,直接找最高版本的打开就对了(其实只要版本大于 24 【Android 7.0 API 级别】都可以)

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝
玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝
玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

好了现在我们找到 apksigner 了,那么怎么用它来签名 APK 呢?

我这里准备了一个待签名的 demo_v001.apk

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

然后在终端执行

/Users/test/android/sdk/build-tools/30.0.3/apksigner  sign --ks /data/keys/app/test.keystore --ks-key-alias by_bin --ks-pass pass:"this_is_password" /Users/test/Desktop/dist/demo_v001.apk

/Users/test/android/sdk/build-tools/30.0.3/apksigner 是我的 apksigner 工具的位置

sign --ks /data/keys/app/test.keystore 这里的 sign --ks 参数后面带上你的签名文件路径

--ks-key-alias by_bin 这里的 --ks-key-alias 参数后面输入你的签名文件别名

--ks-pass pass:"this_is_password" 这里的 --ks-pass 参数带上密码,密码前面加上 pass: 是表示这是一个密码字符串然后在双引号中将密码输入进去,这里其实是支持其他几种方式输入密码的比如 env 文件啥的,具体可以看看官方文档

/Users/test/Desktop/dist/demo_v001.apk 最后这里就是等待签名的 APK 文件路径啦

签名之后文件夹会多出一个 .idsig 为后缀的文件,这个文件是签名之前的 APK 备份,原来的 APK 文件这时候就已经被签好名了。

玩转 Android APK 签名,是时候该用上 apksigner 工具给你的 APP 签名了-天真的小窝

来自官网的示例

为 APK 签名

使用 release.jks(密钥库中唯一的密钥)为 APK 签名:

apksigner sign --ks release.jks app.apk

使用私钥和证书(存储为不同的文件)为 APK 签名:

apksigner sign --key release.pk8 --cert release.x509.pem app.apk

使用两个密钥为 APK 签名:

apksigner sign --ks first-release-key.jks --next-signer --ks second-release-key.jks app.apk

验证 APK 签名

检查 APK 的签名是否可在 APK 支持的所有 Android 平台上被确认为有效:

apksigner verify app.apk

检查 APK 的签名是否可在 Android 4.0.3(API 级别 15)及更高版本上被确认为有效:

apksigner verify --min-sdk-version 15 app.apk

轮替签名密钥

启用支持密钥轮替的签名证书沿袭:

apksigner rotate --out /path/to/new/file --old-signer \
    --ks release.jks --new-signer --ks release2.jks

再次轮替您的签名密钥:

apksigner rotate --in /path/to/existing/lineage \
  --out /path/to/new/file --old-signer --ks release2.jks \
  --new-signer --ks release3.jks

android 开发团队 apksigner 官方文档:https://developer.android.com/studio/command-line/apksigner?hl=zh-cn