Android APK 签名基础:V1、V2、V3、V4 一网打尽

做 Android 开发这些年,签名这事儿我打交道最多。别小看它,签名的选择直接影响你包体积、增量更新、甚至用户隐私合规。今天咱们就把 V1、V2、V3、V4 这四个签名方案掰开揉碎,讲清楚它们到底是什么、怎么选。

一句话先记住:签名不是加文件,而是保护 APK 完整性和来源可信度。你装的每个 App 都经过签名验证,否则系统直接拒绝安装。

V1 签名——最古老,也最兼容

V1 是 Android 1.0 时代就有的方案。说白了,它把签名信息放在 APK 文件内的 META-INF/ 目录下,用三个文件搞定:MANIFEST.MF、CERT.SF、CERT.RSA。

  • 工作方式:对 APK 里的每个非签名文件单独计算 SHA1 摘要,存到 MANIFEST.MF;再用私钥对摘要签名,生成 CERT.SF 和 CERT.RSA。
  • 优点:兼容 Android 7.0 以下所有设备,老项目迁移无压力。
  • 缺点:只保护了文件内容,没保护 APK 文件结构。恶意程序可以解压、修改、重新打包后,只要保留 META-INF/ 里的签名文件,就能绕过校验。

我曾踩过坑:有一次接入第三方 SDK,对方给的 AAR 里混了 V1 签名。我在 Android 11 设备上测试一切正常,结果发布后被用户反馈安装失败——因为 SDK 里的单个文件被系统安全策略识别为可篡改。最后逼着对方升级签名方案才解决。

V2 签名——全文件保护,更安全

Android 7.0(API 24)引入了 V2 签名。它把签名信息嵌入到 APK 的 ZIP 中央目录之前,对整包做签名,包括 ZIP 条目(文件列表、压缩方式、偏移量等)都纳入校验。

  • 校验逻辑:安装时解析 ZIP 结构,找到签名块,验证整个包是否被篡改。
  • 优点:
    • 阻止了中间人修改 ZIP 结构,安全性提升明显。
    • 与 V1 兼容,可以同时使用两种签名(回退校验)。
  • 缺点:对增量更新不友好。APK 签名块修改后,整个包的哈希都变了,导致差分补丁不能再做。

你想想看,如果你的 App 要做增量更新(比如 Google Play 的 apk-expansion-files 或国内厂商的分包),V2 签名会增加包体积——因为差分工具根本没法利用原来的签名块了。我个人习惯是:只要目标设备是 Android 8.0 以上,只打 V2 签名就能省点体积。

V3 签名——密钥轮换,生命周期更灵活

V3 在 Android 9.0(API 28)推出。它最大的亮点是:支持密钥轮换。什么意思?就是你的 App 可以换签名密钥,但系统仍然信任它。

实现原理:签名块里链式存储了历史签名信息,每个新密钥签名时附带上一轮的签名证明。系统安装时会沿着链条验证整个信任链。

特性 V2 V3
密钥轮换 不支持 支持(通过签名链)
兼容性 Android 7.0+ Android 9.0+
包体积影响 增加少量元数据(约 1~2 KB) 增加签名链长度(约 2~4 KB / 每轮)

我建议:如果你的 App 生命周期超过三年,或者有换包名、换企业主体等场景,现在就启用 V3 签名。密钥轮换策略能让你在未来优雅过渡——否则你只能发新包,旧用户要卸载重装。

V4 签名——专为增量更新而生

V4 签名是 Android 11 开始支持的。它不直接替换 V2/V3,而是额外生成一个独立的签名文件(.idsig),用来支持流式安装和更精准的增量补丁。

  • 核心特性:签名信息分离,系统可以在解压过程中逐块验证,不用等全部下载完。
  • 对包体积的影响:V4 签名本身不改变 APK 内容,签名文件单独存储。但 AGP(Android Gradle Plugin)在打 Release 包时默认会生成 .idsig 文件,如果你不小心把它连带上传到应用商店,就会白白多出几百 KB 的体积。

注意:很多团队在 CI/CD 流水线里没清理 .idsig 文件,结果发现 APK 包体积莫名大了 200~500 KB。我建议你在打包脚本里显式排除 *.idsig,或者用 --no-v4-signature 参数关闭 V4 生成(除非你明确需要流式安装)。

实战对比:怎么选?

下面这张表格覆盖了主流场景下的推荐配置。记住,签名方案可以叠加——AGP 默认同时打 V1+V2+V3 是安全的,但你得根据目标设备版本做取舍。

场景 推荐方案 包体积影响 说明
兼容所有设备(minSdk <24) V1 + V2 增加约 5 KB V1 保证旧设备,V2 保证安全性
仅支持 Android 7.0+ 仅 V2 减少约 3 KB(无 META-INF) 去掉 V1 能省一个目录
支持密钥轮换 V2 + V3 增加约 4~6 KB V3 签名链有额外开销
需要增量更新(流式) V2 + V3 + V4 注意排除 .idsig V4 只生成独立文件,不嵌入 APK
APK 签名方案演进与对比 APK 签名方案演进与对比 V1 签名 JAR 签名,兼容最广 Android 1.0+ V2 签名 全文件保护 Android 7.0+ V3 签名 支持密钥轮换 Android 9.0+ V4 签名 增量验证专用 Android 11.0+ 关键影响:包体积与兼容性 • V1 增加 META-INF 目录(约 3 KB) • V2/V3 签名块嵌入 APK,增加 1~6 KB • V4 生成独立 .idsig 文件(数百 KB),默认生成需清理 所有方案可以共存,系统按最大版本校验 选择策略:无脑 V2+V3,旧设备补 V1,增量补 V4

AGP 中如何控制签名配置?

在 build.gradle.kts 或 build.gradle 中,你可以通过 signingConfig 块精确控制启用哪些签名方案。下面是一个典型生产配置:

android {
    signingConfigs {
        create("release") {
            keyAlias = "my-alias"
            keyPassword = "****"
            storeFile = file("my-key.jks")
            storePassword = "****"
            // 默认启用 V1+V2,我们可以显式关闭 V1 只留 V2 和 V3
            enableV1Signing = false
            enableV2Signing = true
            enableV3Signing = true
            enableV4Signing = false  // 关闭 V4 避免生成 .idsig
        }
    }
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

这段代码里我故意关了 V1 和 V4。为什么?因为我的 minSdk 是 24,V1 根本没用了。V4 呢,我不做流式安装,而且 CI 脚本经常忘删 .idsig,干脆在源头掐掉。

注意:如果你关闭了 V1 签名,但 minSdk < 24,那么 Android 6.0 及以下设备会直接拒绝安装!所以别图省体积就不加 V1——除非你确定用户群没有低版本设备。我曾经给一个企业 App 关掉 V1 后,老板的手机(Android 5.1)死活装不上,最后被骂了一顿……

总结一下

签名方案没有“最新最好”的说法,只有“适不适合你的场景”。V1 兼容但弱安全,V2 安全但不支持密钥轮换,V3 灵活但有体积开销,V4 是增量更新利器但也带来额外文件。我的习惯是:

  • 目标 SDK < 24:V1 + V2
  • minSdk = 24~28:V2 + V3
  • minSdk ≥ 29:仅 V2 + V3(或加 V4 按需)