apksigner

apksigner 工具是 Android SDK Build Tools 24.0.3 及更高版本中提供的工具,可让您对 APK 进行签名,并确认 APK 的签名将在该 APK 支持的所有 Android 平台版本上成功验证。

本页面提供了该工具的简短使用指南,并作为该工具支持的不同命令行选项的参考。有关如何使用 apksigner 工具对 APK 进行签名的更完整说明,请参阅为应用签名

注意:如果您使用 apksigner 对 APK 签名后又对 APK 进行更改,APK 的签名将失效。如果您使用 zipalign 对 APK 进行对齐,请在对 APK 签名之前使用它。

用法

对 APK 签名

使用 apksigner 工具对 APK 进行签名的语法如下

apksigner sign --ks keystore.jks |
  --key key.pk8 --cert cert.x509.pem
  [signer_options] app-name.apk

使用 apksigner 工具对 APK 签名时,您必须提供签名者的私钥和证书。您可以通过两种方式包含此信息

  • 使用 --ks 选项指定 KeyStore 文件。
  • 分别使用 --key--cert 选项指定私钥文件和证书文件。私钥文件必须使用 PKCS #8 格式,证书文件必须使用 X.509 格式。

通常,您只使用一个签名者对 APK 签名。如果您需要使用多个签名者对 APK 签名,请使用 --next-signer 选项来分隔要应用于每个签名者的通用选项集。

apksigner sign [signer_1_options] --next-signer [signer_2_options] app-name.apk

验证 APK 的签名

在受支持的平台上确认 APK 签名成功验证的语法如下

apksigner verify [options] app-name.apk

轮换签名密钥

轮换签名证书谱系(即新的签名序列)的语法如下

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

选项

以下列表包含 apksigner 工具支持的每个命令的选项集。

sign 命令

apksigner sign 命令具有以下选项。

通用选项

以下选项指定要应用于签名者的基本设置

--out <apk 文件名>
您希望保存已签名 APK 的位置。如果未明确提供此选项,APK 包将在原位签名,这将覆盖输入 APK 文件。
--min-sdk-version <整数>
apksigner 用于确认 APK 签名将得到验证的最低 Android 框架 API 级别。更高的值允许工具在签署应用时使用更强的安全参数,但会将 APK 的可用性限制在运行较新版本 Android 的设备上。默认情况下,apksigner 使用应用清单文件中 minSdkVersion 属性的值。
--max-sdk-version <整数>
apksigner 用于确认 APK 签名将得到验证的最高 Android 框架 API 级别。默认情况下,该工具使用最高的可能 API 级别。
--rotation-min-sdk-version <整数>
APK 轮换签名密钥应使用的最低 API 级别,以生成 APK 的签名。APK 的原始(未轮换)签名密钥将用于所有先前的平台版本。默认情况下,轮换签名密钥(在运行 Android 13 (API 级别 33) 或更高版本的设备上受支持)与 v3.1 签名块一起使用。

注意: 如果您的应用已在运行 Android 12L(API 级别 32)或更低版本的设备上通过轮换签名密钥进行签名,那么您必须使用 --rotation-min-sdk-version 28 才能继续使用 Android 9(API 级别 28)的轮换签名密钥对应用进行签名。

--v1-signing-enabled <true | false>
确定 apksigner 是否使用传统的基于 JAR 的签名方案对给定的 APK 包进行签名。默认情况下,该工具使用 --min-sdk-version--max-sdk-version 的值来决定何时应用此签名方案。
--v2-signing-enabled <true | false>
确定 apksigner 是否使用APK 签名方案 v2 对给定的 APK 包进行签名。默认情况下,该工具使用 --min-sdk-version--max-sdk-version 的值来决定何时应用此签名方案。
--v3-signing-enabled <true | false>
确定 apksigner 是否使用APK 签名方案 v3 对给定的 APK 包进行签名。默认情况下,该工具使用 --min-sdk-version--max-sdk-version 的值来决定何时应用此签名方案。
--v4-signing-enabled <true | false | only>

确定 apksigner 是否使用APK 签名方案 v4 对给定的 APK 包进行签名。此方案会在单独的文件(apk-name.apk.idsig)中生成签名。如果为 true 且 APK 未签名,则会根据 --min-sdk-version--max-sdk-version 的值生成 v2 或 v3 签名。然后,该命令会根据已签名 APK 的内容生成 .idsig 文件。

使用 only 仅生成 v4 签名,而不修改 APK 及其在调用之前拥有的任何签名。only 失败的原因是 APK 尚未具有 v2 或 v3 签名,或者签名使用的密钥与当前调用提供的密钥不同。

默认情况下,该工具使用 --min-sdk-version--max-sdk-version 的值来决定何时应用此签名方案。

-v, --verbose
使用详细输出模式。

每个签名者选项

以下选项指定特定签名者的配置。如果您只使用一个签名者对应用签名,则无需这些选项。

--next-signer <签名者选项>
用于为每个签名者指定不同的通用选项。
--v1-signer-name <基本名称>
构成当前签名者的基于 JAR 的签名的文件的基本名称。默认情况下,apksigner 使用 KeyStore 的密钥别名或此签名者密钥文件的基本名称。

密钥和证书选项

以下选项指定签名者的私钥和证书

--ks <文件名>
签名者的私钥和证书链位于给定的基于 Java 的 KeyStore 文件中。如果文件名设置为 "NONE",则包含密钥和证书的 KeyStore 不需要指定文件,某些 PKCS #11 KeyStore 就是这种情况。
--ks-key-alias <别名>
表示签名者私钥和 KeyStore 中证书数据的别名名称。如果与签名者关联的 KeyStore 包含多个密钥,则必须指定此选项。
--ks-pass <输入格式>

包含签名者私钥和证书的 KeyStore 的密码。您必须提供密码才能打开 KeyStore。apksigner 工具支持以下格式

  • pass:<password> – 密码与 apksigner sign 命令的其余部分内联提供。
  • env:<name> – 密码存储在给定的环境变量中。
  • file:<filename> – 密码作为单行存储在给定文件中。
  • stdin – 密码作为单行在标准输入流中提供。这是 --ks-pass 的默认行为。

注意: 如果您在同一个文件中包含多个密码,请将它们指定在不同的行上。apksigner 工具根据您指定签名者的顺序将密码与 APK 的签名者关联。如果您为签名者提供了两个密码,apksigner 会将第一个密码解释为 KeyStore 密码,将第二个密码解释为密钥密码。

--pass-encoding <字符集>
在尝试处理包含非 ASCII 字符的密码时,包含指定的字符编码,例如 ibm437utf-8

Keytool 通常通过使用控制台的默认字符集转换密码来加密密钥库。默认情况下,apksigner 尝试使用几种形式的密码进行解密

  • Unicode 形式
  • 使用 JVM 默认字符集编码的形式
  • 在 Java 8 及更早版本中,使用控制台的默认字符集编码的形式
  • 在 Java 9 中,apksigner 无法检测控制台的字符集。当使用非 ASCII 密码时,您可能需要指定 --pass-encoding。您可能还需要在使用 Keytool 在不同操作系统或不同区域设置中创建的 KeyStore 中指定此选项。

    --key-pass <输入格式>

    签名者私钥的密码,如果私钥受密码保护,则需要此密码。apksigner 工具支持以下格式

    • pass:<password> – 密码与 apksigner sign 命令的其余部分内联提供。
    • env:<name> – 密码存储在给定的环境变量中。
    • file:<filename> – 密码作为单行存储在给定文件中。
    • stdin – 密码作为单行在标准输入流中提供。这是 --key-pass 的默认行为。
    --ks-type <算法>
    与包含签名者私钥和证书的 KeyStore 相关联的类型或算法。默认情况下,apksigner 使用 Security 属性文件中定义为 keystore.type 常量。
    --ks-provider-name <名称>
    在请求签名者的 KeyStore 实现时要使用的 JCA Provider 名称。默认情况下,apksigner 使用最高优先级的提供程序。
    --ks-provider-class <类名>
    在请求签名者的 KeyStore 实现时要使用的 JCA Provider 的完全限定类名。此选项可替代 --ks-provider-name。默认情况下,apksigner 使用 --ks-provider-name 选项指定的提供程序。
    --ks-provider-arg <值>
    一个字符串值,作为 JCA Provider 类构造函数的参数传入;该类本身由 --ks-provider-class 选项定义。默认情况下,apksigner 使用该类的零参数构造函数。
    --key <文件名>
    包含签名者私钥的文件的名称。此文件必须使用 PKCS #8 DER 格式。如果密钥受密码保护,apksigner 会提示通过标准输入输入密码,除非您使用 --key-pass 选项指定不同类型的输入格式。
    --cert <文件名>
    包含签名者证书链的文件的名称。此文件必须使用 X.509 PEM 或 DER 格式。

    verify 命令

    apksigner verify 命令具有以下选项。

    --print-certs
    显示有关 APK 签名证书的信息。
    --min-sdk-version <整数>
    apksigner 用于确认 APK 签名将得到验证的最低 Android 框架 API 级别。更高的值允许工具在签署应用时使用更强的安全参数,但会将 APK 的可用性限制在运行较新版本 Android 的设备上。默认情况下,apksigner 使用应用清单文件中 minSdkVersion 属性的值。
    --max-sdk-version <整数>
    apksigner 用于确认 APK 签名将得到验证的最高 Android 框架 API 级别。默认情况下,该工具使用最高的可能 API 级别。
    -v, --verbose
    使用详细输出模式。
    -Werr
    将警告视为错误。

    示例

    以下是使用 apksigner 的示例。

    对 APK 签名

    使用 release.jks(KeyStore 中的唯一密钥)对 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 签名,并将轮换目标设为 SDK 28+

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage app.apk \
      --rotation-min-sdk-version 28
    

    使用轮换签名密钥对 APK 签名,并将轮换目标设为 SDK 33+

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage 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