apksigner

Narzędzie apksigner, dostępne w pakiecie Android SDK Build Tools w wersji 24.0.3 lub nowszej, umożliwia podpisywanie plików APK i potwierdzanie, że podpis pliku APK zostanie pomyślnie zweryfikowany na wszystkich obsługiwanych wersjach platformy Androida.

Na tej stronie znajdziesz krótki przewodnik po korzystaniu z tego narzędzia oraz opis różnych opcji wiersza poleceń, które są przez nie obsługiwane. Bardziej szczegółowy opis tego, jak narzędzie apksigner służy do podpisywania plików APK, znajdziesz w artykule Podpisywanie aplikacji.

Ostrzeżenie: jeśli podpiszesz plik APK za pomocą narzędzia apksigner i wprowadzisz w nim dalsze zmiany, podpis pliku APK zostanie unieważniony. Jeśli do wyrównania pliku APK używasz narzędzia zipalign, zrób to przed podpisaniem pliku.

Wykorzystanie

Podpisywanie pliku APK

Składnia podpisywania pliku APK za pomocą narzędzia apksigner jest taka:

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

Podczas podpisywania pliku APK za pomocą narzędzia apksigner musisz podać klucz prywatny i certyfikat osoby podpisującej. Możesz podać te informacje na 2 sposoby:

  • Określ plik magazynu kluczy za pomocą opcji --ks.
  • Określ osobno plik klucza prywatnego i plik certyfikatu, używając odpowiednio opcji --key--cert. Plik klucza prywatnego musi być w formacie PKCS #8, a plik certyfikatu musi być w formacie X.509.

Zazwyczaj plik APK jest podpisywany tylko przez jednego sygnatariusza. Jeśli chcesz podpisać plik APK za pomocą kilku sygnatariuszy, użyj opcji --next-signer, aby oddzielić zestaw opcji ogólnych, które mają być stosowane do każdego sygnatariusza:

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

Weryfikowanie podpisu pliku APK

Składnia potwierdzająca pomyślną weryfikację podpisu pliku APK na obsługiwanych platformach jest następująca:

apksigner verify [options] app-name.apk

Rotacja kluczy podpisywania

Składnia wymiany ciągu certyfikatów podpisywania lub nowej sekwencji podpisów jest następująca:

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

Opcje

Poniższe listy zawierają zestaw opcji dla każdego polecenia obsługiwanego przez narzędzie apksigner.

Polecenie podpisywania

Polecenie znaku apksigner ma te opcje:

Opcje ogólne

Te opcje określają podstawowe ustawienia, które mają być stosowane do osoby podpisującej:

--out <apk-filename>
Lokalizacja, w której chcesz zapisać podpisany pakiet APK. Jeśli ta opcja nie jest podana wprost, pakiet APK jest podpisywany w miejscu, co powoduje zastąpienie wejściowego pliku APK.
--min-sdk-version <integer>
Najniższy poziom interfejsu API platformy Android, którego apksigner używa do potwierdzenia, że podpis pliku APK zostanie zweryfikowany. Wyższe wartości umożliwiają narzędziu używanie silniejszych parametrów zabezpieczeń podczas podpisywania aplikacji, ale ograniczają dostępność pliku APK do urządzeń z nowszymi wersjami Androida. Domyślnie apksigner używa wartości atrybutu minSdkVersion z pliku manifestu aplikacji.
--max-sdk-version <integer>
Najwyższy poziom interfejsu API platformy Androida, którego apksigner używa do potwierdzenia, że podpis pliku APK zostanie zweryfikowany. Domyślnie narzędzie używa najwyższego możliwego poziomu interfejsu API.
--rotation-min-sdk-version <integer>
Najniższy poziom interfejsu API, którego obrócony klucz podpisywania pliku APK powinien używać do tworzenia podpisu pliku APK. W przypadku wszystkich poprzednich wersji platformy będzie używany oryginalny (nieobrócony) klucz podpisywania pliku APK. Domyślnie klucze podpisywania, które są obsługiwane na urządzeniach z Androidem 13 (API na poziomie 33) lub nowszym, są używane z blokiem podpisywania w wersji 3.1.

Uwaga: jeśli Twoja aplikacja została podpisana obróconym kluczem podpisywania na urządzeniu z Androidem 12L (poziom interfejsu API 32) lub starszym, musisz użyć --rotation-min-sdk-version 28, aby nadal podpisywać aplikację obróconym kluczem podpisywania w przypadku Androida 9 (poziom interfejsu API 28).

--v1-signing-enabled <true | false>
Określa, czy apksigner podpisuje dany pakiet APK przy użyciu tradycyjnego schematu podpisywania opartego na plikach JAR. Domyślnie narzędzie używa wartości --min-sdk-version--max-sdk-version, aby określić, kiedy zastosować ten schemat podpisu.
--v2-signing-enabled <true | false>
Określa, czy apksigner podpisuje dany pakiet APK przy użyciu schematu podpisu APK w wersji 2. Domyślnie narzędzie używa wartości --min-sdk-version--max-sdk-version, aby określić, kiedy zastosować ten schemat podpisu.
--v3-signing-enabled <true | false>
Określa, czy apksigner podpisuje dany pakiet APK przy użyciu schematu podpisu APK w wersji 3. Domyślnie narzędzie używa wartości --min-sdk-version--max-sdk-version, aby określić, kiedy zastosować ten schemat podpisu.
--v4-signing-enabled <true | false | only>

Określa, czy apksigner podpisuje dany pakiet APK przy użyciu schematu podpisu APK w wersji 4. Ten schemat tworzy podpis w osobnym pliku (apk-name.apk.idsig). Jeśli true i plik APK nie są podpisane, generowany jest podpis w wersji 2 lub 3 na podstawie wartości --min-sdk-version--max-sdk-version. Następnie polecenie tworzy plik .idsig na podstawie zawartości podpisanego pliku APK.

Użyj only, aby wygenerować tylko podpis w wersji 4 bez modyfikowania pliku APK ani żadnych podpisów, które miał przed wywołaniem. only kończy się niepowodzeniem, jeśli plik APK nie ma jeszcze podpisu w wersji 2 lub 3 albo jeśli podpis został utworzony przy użyciu innego klucza niż ten, który został podany w bieżącym wywołaniu.

Domyślnie narzędzie używa wartości --min-sdk-version--max-sdk-version, aby określić, kiedy zastosować ten schemat podpisu.

-v, --verbose
Użyj trybu szczegółowych danych wyjściowych.

Opcje dla poszczególnych osób podpisujących

Poniższe opcje określają konfigurację konkretnego sygnatariusza. Te opcje nie są konieczne, jeśli podpisujesz aplikację tylko jednym sygnatariuszem.

--next-signer <signer-options>
Służy do określania różnych opcji ogólnych dla każdego sygnatariusza.
--v1-signer-name <basename>
Nazwa podstawowa plików, które składają się na sygnaturę opartą na pliku JAR dla bieżącego sygnatariusza. Domyślnie apksigner używa aliasu klucza z magazynu kluczy lub nazwy podstawowej pliku klucza dla tego sygnatariusza.

Opcje klucza i certyfikatu

Poniższe opcje określają klucz prywatny i certyfikat osoby podpisującej:

--ks <filename>
Klucz prywatny i łańcuch certyfikatów sygnującego znajdują się w podanym pliku magazynu kluczy Java. Jeśli nazwa pliku jest ustawiona na "NONE", magazyn kluczy zawierający klucz i certyfikat nie musi mieć określonego pliku, co ma miejsce w przypadku niektórych magazynów kluczy PKCS #11.
--ks-key-alias <alias>
Nazwa aliasu reprezentującego klucz prywatny i dane certyfikatu osoby podpisującej w magazynie kluczy. Jeśli magazyn kluczy powiązany z podpisującym zawiera wiele kluczy, musisz określić tę opcję.
--ks-pass <input-format>

Hasło do magazynu kluczy zawierającego klucz prywatny i certyfikat osoby podpisującej. Aby otworzyć KeyStore, musisz podać hasło. Narzędzie apksigner obsługuje te formaty:

  • pass:<password> – hasło podane w wierszu z pozostałą częścią polecenia apksigner sign.
  • env:<name> – hasło jest przechowywane w podanej zmiennej środowiskowej.
  • file:<filename> – hasło jest przechowywane jako pojedynczy wiersz w danym pliku.
  • stdin – hasło jest podawane jako pojedynczy wiersz w standardowym strumieniu wejściowym. Jest to domyślne działanie w przypadku --ks-pass.

Uwaga: jeśli w tym samym pliku umieścisz kilka haseł, wpisz je w oddzielnych wierszach. Narzędzie apksigner przypisuje hasła do osób podpisujących plik APK na podstawie kolejności, w jakiej je określisz. Jeśli podasz 2 hasła dla osoby podpisującej,apksigner zinterpretuje pierwsze hasło jako hasło do KeyStore, a drugie jako hasło do klucza.

--pass-encoding <charset>
Zawiera określone kodowania znaków, np. ibm437 lub utf-8, podczas próby obsługi haseł zawierających znaki inne niż ASCII.

Narzędzie Keytool często szyfruje magazyny kluczy, konwertując hasło przy użyciu domyślnego zestawu znaków konsoli. Domyślnie apksigner próbuje odszyfrować plik za pomocą kilku form hasła:

  • Forma Unicode
  • Formularz zakodowany przy użyciu domyślnego zestawu znaków JVM.
  • W przypadku Javy 8 i starszych wersji formularz jest kodowany przy użyciu domyślnego zestawu znaków konsoli.
  • W przypadku Javy 9 apksigner nie może wykryć zestawu znaków konsoli. W przypadku użycia hasła zawierającego znaki inne niż ASCII może być konieczne podanie --pass-encoding. Może być też konieczne określenie tej opcji w przypadku magazynów kluczy utworzonych za pomocą narzędzia keytool w innym systemie operacyjnym lub w innych ustawieniach regionalnych.

    --key-pass <input-format>

    Hasło do klucza prywatnego osoby podpisującej, które jest potrzebne, jeśli klucz prywatny jest chroniony hasłem. Narzędzie apksigner obsługuje te formaty:

    • pass:<password> – hasło jest podawane w wierszu z pozostałą częścią polecenia apksigner sign.
    • env:<name> – hasło jest przechowywane w podanej zmiennej środowiskowej.
    • file:<filename> – hasło jest przechowywane jako pojedynczy wiersz w danym pliku.
    • stdin – hasło jest podawane jako pojedynczy wiersz w standardowym strumieniu wejściowym. Jest to domyślne działanie w przypadku --key-pass.
    --ks-type <algorithm>
    Typ lub algorytm powiązany z magazynem kluczy, który zawiera klucz prywatny i certyfikat sygnującego. Domyślnie apksigner używa typu zdefiniowanego jako stała keystore.type w pliku właściwości zabezpieczeń.
    --ks-provider-name <name>
    Nazwa dostawcy JCA, który ma być używany podczas wysyłania prośby o implementację magazynu kluczy sygnującego. Domyślnie usługa apksigner korzysta z dostawcy o najwyższym priorytecie.
    --ks-provider-class <class-name>
    Pełna nazwa klasy dostawcy JCA, która ma być używana podczas wysyłania żądania implementacji magazynu kluczy sygnującego. Ta opcja jest alternatywą dla --ks-provider-name. Domyślnie apksigner używa dostawcy określonego za pomocą opcji --ks-provider-name.
    --ks-provider-arg <value>
    Ciąg znaków, który ma być przekazywany jako argument konstruktora klasy dostawcy JCA. Sama klasa jest definiowana za pomocą opcji --ks-provider-class. Domyślnie apksignerużywa konstruktora klasy bez argumentów.
    --key <filename>
    Nazwa pliku zawierającego klucz prywatny sygnatariusza. Ten plik musi być w formacie PKCS #8 DER. Jeśli klucz jest chroniony hasłem, apksigner wyświetli prośbę o jego podanie za pomocą standardowego wejścia, chyba że określisz inny rodzaj formatu wejściowego za pomocą opcji apksigner.--key-pass
    --cert <filename>
    Nazwa pliku zawierającego łańcuch certyfikatów osoby podpisującej. Ten plik musi być w formacie X.509 PEM lub DER.

    Sprawdzanie polecenia

    Polecenie apksigner verify ma te opcje:

    --print-certs
    Wyświetl informacje o certyfikatach podpisywania pakietu APK.
    --print-certs-pem
    Wyświetla informacje o certyfikatach podpisywania pliku APK i drukuje kodowanie PEM każdego certyfikatu podpisywania na standardowe wyjście.
    --min-sdk-version <integer>
    Najniższy poziom interfejsu API platformy Android, którego apksigner używa do potwierdzenia, że podpis pliku APK zostanie zweryfikowany. Wyższe wartości umożliwiają narzędziu używanie silniejszych parametrów zabezpieczeń podczas podpisywania aplikacji, ale ograniczają dostępność pliku APK do urządzeń z nowszymi wersjami Androida. Domyślnie apksigner używa wartości atrybutu minSdkVersion z pliku manifestu aplikacji.
    --max-sdk-version <integer>
    Najwyższy poziom interfejsu API platformy Androida, którego apksigner używa do potwierdzenia, że podpis pliku APK zostanie zweryfikowany. Domyślnie narzędzie używa najwyższego możliwego poziomu interfejsu API.
    -v, --verbose
    Użyj trybu szczegółowych danych wyjściowych.
    -Werr
    Traktuj ostrzeżenia jako błędy.

    Przykłady

    Oto przykłady użycia właściwości apksigner.

    Podpisywanie pliku APK

    Podpisz plik APK za pomocą klucza release.jks, który jest jedynym kluczem w KeyStore:

    $ apksigner sign --ks release.jks app.apk
    

    Podpisz plik APK za pomocą klucza prywatnego i certyfikatu przechowywanych jako oddzielne pliki:

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

    Podpisywanie pliku APK za pomocą 2 kluczy:

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

    Podpisz plik APK za pomocą klucza podpisywania, który został poddany rotacji, i pakietu SDK w wersji 28 lub nowszej:

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

    Podpisz plik APK za pomocą klucza podpisywania, który został poddany rotacji, i wersji pakietu SDK 33 lub nowszej:

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

    Weryfikowanie podpisu pliku APK

    Sprawdź, czy podpisy pliku APK powinny zostać potwierdzone jako prawidłowe na wszystkich platformach Androida, które obsługuje ten plik:

    $ apksigner verify app.apk
    

    Sprawdź, czy podpisy pliku APK powinny zostać potwierdzone jako prawidłowe na Androidzie 4.0.3 (API na poziomie 15) i nowszym:

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

    Rotacja kluczy podpisywania

    Włączanie linii certyfikatów podpisywania, która obsługuje rotację kluczy:

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

    Ponownie wykonaj rotację kluczy podpisywania:

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