如何使用 jarsigner 和 apksigner 对 APK 进行签名?两者有何区别?
解读
国内面试中,这道题常作为“APK 发布流程”环节的追问,用来区分候选人是否真正走过上线全链路。面试官期望听到三条主线:
- 命令行实操:密钥格式、签名算法、输出对齐。
- 版本差异:v1 scheme(JAR 签名)与 v2/v3 scheme(APK 签名)的验证时机、校验范围、性能影响。
- 国内合规:应用商店对 v2 签名的强制要求、工信部备案对签名指纹的回传。
答不到“v2 签名必须开启”“apksigner 支持轮转”容易被打回“只是跑过 gradle 任务”。
知识点
- 签名链:jarsigner 只生成 JAR 式 META-INF 内 .SF/.RSA,apksigner 额外生成整个 APK 的 v2/v3 签名分块。
- 验证阶段:PackageManagerService 在安装时先按 v3→v2→v1 顺序尝试,任一通过即可;但国内主流市场(华为、OPPO、小米)已拒绝仅含 v1 的 APK。
- 密钥格式:jarsigner 只认 JKS/PKCS12,apksigner 只认 PKCS8+PKCS12,且要求私钥算法为 RSA/ECDSA,DSA 已被废弃。
- 对齐:jarsigner 签名后必须手动 zipalign;apksigner 要求“先对齐后签名”,否则直接报错。
- 轮转:apksigner 支持 v3 scheme 的轮转签名,可实现旧签名到新签名的无缝切换,jarsigner 无此能力。
- 性能:v2 签名把哈希树写进中央目录,安装时一次性校验,比 v1 逐文件解压哈希快 30% 以上,对低端机 OTA 升级尤其明显。
- 安全:v2 签名覆盖整个 ZIP 结构,防止二次打包插入广告 SDK;v1 仅保护单个 entry,容易被“空文件注入”绕过。
- 工具链:Android SDK 30+ 已将 apksigner 从 build-tools 独立,CI 镜像需显式安装;jarsigner 依赖 JDK,版本差异会导致签名算法兼容问题(JDK8 默认 SHA1,已被商店拒绝)。
答案
一、jarsigner 签名步骤(仅 v1,不推荐单独上线)
- 生成兼容密钥
keytool -genkeypair -alias release -keyalg RSA -keysize 2048 -validity 9125 -keystore release.jks - 对齐(必须在签名前,否则后续 zipalign 会破坏签名)
zipalign -f -p 4 app-unsigned.apk app-aligned.apk - 签名
jarsigner -keystore release.jks -signedjar app-signed-v1.apk app-aligned.apk release
参数说明:
-sigalg SHA256withRSA -digestalg SHA-256 -tsa http://timestamp.digicert.com - 验证
jarsigner -verify -verbose -certs app-signed-v1.apk
二、apksigner 签名步骤(v1+v2+v3 同时开启,国内上线标配)
- 转换密钥到 PKCS12(若原为 JKS)
keytool -importkeystore -srckeystore release.jks -destkeystore release.p12 -deststoretype PKCS12 - 对齐(必须先行)
zipalign -f -p 4 app-unsigned.apk app-aligned.apk - 签名
apksigner sign --ks release.p12 --ks-key-alias release --out app-signed.apk app-aligned.apk
可选参数:
--v1-signing-enabled true --v2-signing-enabled true --v3-signing-enabled true
--min-sdk-version 21 --max-sdk-version 34 - 验证
apksigner verify -v --print-certs app-signed.apk
输出中必须看到 “Verified using v1 scheme (JAR): true” “v2 scheme (APK Signature Scheme v2): true” 才算商店合规。
三、两者核心区别
- 签名位置:jarsigner 把签名写在 META-INF;apksigner 额外在 ZIP 中央目录与 EOCD 之间插入 v2/v3 分块。
- 校验范围:v1 只校验单个 entry,v2/v3 覆盖整个 APK,杜绝“二次打包”。
- 性能:v2 安装耗时降低 30%+,对国内低端机群显著。
- 轮转:apksigner 支持 v3 的轮转密钥,jarsigner 无。
- 对齐顺序:jarsigner 先签后对齐,apksigner 先对齐后签,顺序颠倒会直接失败。
- 商店政策:国内 Top200 渠道 2022 年起已拒绝仅 v1 签名,海外 Google Play 2023 年强制 v2。
拓展思考
- 混合签名场景:若企业旧 APK 使用 DSA+SHA1,需先在 v3 轮转中引入 RSA+SHA256,再逐步下线老密钥;轮转过程需保证旧用户覆盖率达到 90% 以上,否则系统会拒绝更新。
- CI 集成:在 GitLab-CI 中,应将 release.p12 放入受保护变量,使用 apksigner 的 --ks-pass env:KS_PASS 方式避免明文密码;同时利用 verify 步骤做二次校验,防止构建缓存污染。
- 合规审计:工信部备案要求上传签名 MD5/SHA256 指纹,apksigner verify 输出的证书指纹可直接用于后台比对;若使用 v3 轮转,需把新旧两条指纹同时备案。
- 安全左移:在 AGP 8+ 中,Google 默认关闭 v1 签名,若仍需兼容 Android 6 以下,需要手动开启 v1,但国内存量市场已低于 1%,可直接放弃。
- 性能极限:对车载与 Wear 这类低功耗设备,可关闭 v1 仅保留 v2,减少 1~2% 的存储占用;但需提前验证系统升级包是否支持,否则 OTA 会回退到 v1 校验导致安装失败。