apksigner

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

Android SDK Build Tools 24.0.3 以上修訂版本提供的 apksigner 工具可讓您簽署 APK,並確認 APK 簽名是否能在 APK 支援的所有 Android 平台版本成功通過驗證。本頁面提供使用這項工具的簡短指南,並提供工具支援的其他指令列選項參考資料。如需關於使用 apksigner 工具簽署 APK 的完整說明,請參閱「簽署應用程式」指南。

注意:如果您使用 apksigner 簽署 APK,且之後變更 APK,APK 的簽名就會失效。 因此,您必須在簽署 APK 前使用 zipalign 等工具。

使用方式

簽署 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 工具支援的各指令選項組合。

簽署指令

一般選項

下列選項可讓您指定套用至簽署者的基本設定:

--out <apk-filename>
儲存已簽署 APK 的位置。如果未明確提供這個選項,則系統會原地簽署 APK 套件,並覆寫輸入的 APK 檔案。
--min-sdk-version <integer>
apksigner 用於確認 APK 簽名能通過驗證的最低 Android 架構 API 級別。較大的值可讓工具在簽署應用程式時使用更強的安全性參數,但會限制 APK 只能在搭載較新版 Android 的裝置上使用。 根據預設,apksigner 會使用應用程式資訊清單檔案中的 minSdkVersion 屬性值。
--max-sdk-version <integer>
apksigner 用於確認 APK 簽名能通過驗證的最高 Android 架構 API 級別。根據預設,這項工具會使用可用的最高 API 級別。
--rotation-min-sdk-version <integer>
最低 API 級別的 APK 輪替簽署金鑰應該用於產生 APK 簽名。APK 的原始 (非輪替) 簽署金鑰將會用於所有舊平台版本。根據預設,輪替簽署金鑰會與 v3.1 簽署區塊搭配使用,且搭載 Android 13 (API 級別 33) 以上版本的裝置都支援這項功能。

注意:如果應用程式曾在搭載 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 以及叫用前 APK 具有的任何簽名;如果 APK 沒有 v2 或 v3 簽名,或是簽名使用的金鑰與提供給目前叫用的金鑰不同,only 就會失敗。 根據預設,工具會使用 --min-sdk-version--max-sdk-version 的值來判斷何時應套用這項簽署配置。
-v--verbose
使用詳細輸出模式。

各簽署者選項

下列選項會指定特定簽署者的設定。如果您僅使用一個簽署者簽署應用程式,則這些為非必要選項。

--next-signer <signer-options>
用於為每個簽署者指定不同的一般選項
--v1-signer-name <basename>
檔案的基本名稱,構成目前簽署者的 JAR 簽名。對於該簽署者,apksigner 預設會使用 KeyStore 的金鑰別名或金鑰檔案基本名稱。

金鑰和憑證選項

下列選項會指定簽署者的私密金鑰和憑證:

--ks <filename>
簽署者的私密金鑰和憑證鏈結會存放在指定的 Java KeyStore 檔案中。如果檔案名稱設為 "NONE",則包含金鑰和憑證的 KeyStore 不需要指定檔案,某些 PKCS #11 KeyStore 就是如此。
--ks-key-alias <alias>
代表 KeyStore 中簽署者私密金鑰和憑證資料的別名名稱。如果與簽署者相關聯的 KeyStore 含有多個金鑰,您就必須指定這個選項。
--ks-pass <input-format>

含有簽署者私密金鑰和憑證的 KeyStore 密碼。您必須提供密碼才能開啟 KeyStore。apksigner 工具支援下列格式:

  • pass:<password>:提供的密碼內嵌於其他 apksigner sign 指令。
  • env:<name>:密碼會儲存在指定的環境變數中。
  • file:<filename>:密碼會以單行儲存在指定的檔案中。
  • stdin:提供的密碼以單行顯示在標準輸入串中。這是 --ks-pass 的預設行為。

注意:如果一個檔案包含多個密碼,請分行列出。apksigner 工具會根據您指定簽署者的順序,將密碼與 APK 簽署者建立關聯。如果您為簽署者提供兩個密碼,apksigner 會將第一個密碼解讀為 KeyStore 密碼,並將第二個密碼解讀為金鑰密碼。

--pass-encoding <charset>
嘗試處理含有非 ASCII 字元的密碼時,納入指定字元編碼 (例如 ibm437utf-8)。

一般來說,Keytool 會使用控制台的預設字元集來轉換密碼,藉此加密 KeyStore。根據預設,apksigner 會嘗試使用多種格式的密碼來解密,分別是萬國碼 (Unicode) 格式、使用 JVM 預設字元集的編碼格式,以及 Java 8 以下版本使用控制台預設字元集的編碼格式。 在 Java 9 中,apksigner 無法偵測控制台的字元集。 因此,如果您使用非 ASCII 密碼,就可能需要指定 --pass-encoding。您可能也需要針對 Keytool 在其他 OS 或不同語言代碼中建立的 KeyStore 指定這個選項。

--key-pass <input-format>

簽署者的私密金鑰密碼 (如果私密金鑰受到密碼保護,就需要用到)。apksigner 工具支援下列格式:

  • pass:<password>:提供的密碼內嵌於其他 apksigner sign 指令。
  • env:<name>:密碼會儲存在指定的環境變數中。
  • file:<filename>:密碼會以單行儲存在指定的檔案中。
  • stdin:提供的密碼以單行顯示在標準輸入串中。這是 --key-pass 的預設行為。

注意:如果一個檔案包含多個密碼,請分行列出。apksigner 工具會根據您指定簽署者的順序,將密碼與 APK 簽署者建立關聯。如果您為簽署者提供兩個密碼,apksigner 會將第一個密碼解讀為 KeyStore 密碼,並將第二個密碼解讀為金鑰密碼。

--ks-type <algorithm>
與包含簽署者私密金鑰和憑證的 KeyStore 相關聯的類型或演算法。根據預設,apksigner 會使用在安全性屬性檔案中定義為 keystore.type 常數的類型。
--ks-provider-name <name>
要求簽署者 KeyStore 實作時使用的 JCA Provider 名稱。根據預設,apksigner 會使用優先順序最高的提供者。
--ks-provider-class <class-name>
要求簽署者 KeyStore 實作時使用的 JCA Provider 完整類別名稱。這個選項可以做為 --ks-provider-name 的替代選項。根據預設,apksigner 會使用 --ks-provider-name 選項指定的提供者。
--ks-provider-arg <value>
傳遞做為 JCA Provider 類別建構函式引數的字串值;類別本身是透過 --ks-provider-class 選項定義。根據預設,apksigner 會使用類別的無引數建構函式。
--key <filename>
包含簽署者私密金鑰的檔案名稱。這個檔案必須使用 PKCS #8 DER 格式。如果金鑰受到密碼保護,apksigner 會提示使用標準輸入格式輸入密碼;除非您有使用 --key-pass 選項指定不同輸入格式。
--cert <filename>
包含簽署者憑證鏈結的檔案名稱。這個檔案必須使用 X.509 PEM 或 DER 格式。

驗證指令

--print-certs
顯示 APK 簽署憑證的相關資訊。
--min-sdk-version <integer>
apksigner 用於確認 APK 簽名能通過驗證的最低 Android 架構 API 級別。較大的值可讓工具在簽署應用程式時使用更強的安全性參數,但會限制 APK 只能在搭載較新版 Android 的裝置上使用。 根據預設,apksigner 會使用應用程式資訊清單檔案中的 minSdkVersion 屬性值。
--max-sdk-version <integer>
apksigner 用於確認 APK 簽名能通過驗證的最高 Android 架構 API 級別。根據預設,這項工具會使用可用的最高 API 級別。
-v--verbose
使用詳細輸出模式。
-Werr
將警告視為錯誤。

範例

簽署 APK

使用 KeyStore 中唯一的金鑰 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,且該輪替指定 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