Schemat podpisu APK w wersji 4

Android 11 obsługuje schemat podpisywania zgodny ze strumieniem danych w pakiecie APK Schemat podpisu w wersji 4. Podpis w wersji 4 jest oparty na drzewie haszu Merkle obliczony na podstawie wszystkich bajtów pliku APK. Ma on ścisłą zgodność ze strukturą drzewa haszu fs-verity (np. zero- dopełnienie). sól i zero dopełnienia ostatniego bloku). Android 11 przechowuje podpis w osobnym pliku, <apk name>.apk.idsigpodpis w wersji 4 wymaga uzupełniającego podpisu v2 lub v3.

Format pliku

Wszystkie pola liczbowe są podane w języku angielskim. Wszystkie pola zajmują dokładnie taką liczbę bajtów jako wartości sizeof(), bez niejawnego dopełnienia lub – wyrównanie zostało dodane.

Poniżej znajduje się struktura pomocnicza, która upraszcza definicje.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Zawartość głównego pliku:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

Parametr hashing_info to parametry używane w drzewie haszowania generacja + główny hasz:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info ma następującą strukturę:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • Element apk_digest zostanie pobrany z bloku podpisywania pakietu APK w wersji 3. Jeśli nie jest, obecna, z bloku v2 (patrz apk_digest),

Aby można było utworzyć i zweryfikować kod signature, musi on być zserializowany te dane do binarnego obiektu blob i przekazać do algorytm podpisywania / weryfikacji jako podpisanych danych:

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_tree to całe drzewo Merkle pliku APK obliczone w sposób opisany w dokumentacji fs-verity.
.

Producenci i konsumenci

apksigner Narzędzie Android SDK generuje teraz plik podpisu w wersji 4 jeśli używasz go z parametrami domyślnymi. Podpisywanie w wersji 4 można wyłączyć w ten sam sposób jak w przypadku innych schematów podpisywania. Może również sprawdzić, czy podpis w wersji 4 prawidłowe.

adb oczekuje, że plik .apk.idsig będzie dostępny obok pliku .apk, gdy uruchamianie polecenia adb install --incremental
Zostanie też użyty plik .idsig do przeprowadzenia instalacji przyrostowej przez jest domyślnie instalowana, a w razie jej braku lub jest nieprawidłowa.

Po utworzeniu sesji instalacji nowy interfejs API instalacji strumieniowego przesyłania danych w funkcji PackageInstaller akceptuje elementy usunięte podpis w wersji 4 jako osobny argument przy dodawaniu pliku do sesji. Na tym etapie pole signing_info jest przekazywane do identyfikatorów incf jako cały blok. Incfs wyodrębnia hasz główny z obiektu blob.

Podczas zatwierdzania sesji instalacji PackageManagerService ioctl do pobrania obiektu blob sign_info z pliku incf, jego przeanalizowania i zweryfikowania podpis.

Przyrostowy komponent wczytywania danych powinien przesyłać strumieniowo część drzewa Merkle do podpisu za pomocą natywnego interfejsu API wczytywania danych.
Polecenie powłoki usługi package install-incremental akceptuje usunięty plik podpisu w wersji 4 zakodowany w formacie base64 jako parametr dodany plik. Odpowiednie drzewo Merkle musi zostać wysłane do polecenia stdin

podsumowanie_apk

apk_digest to pierwsze dostępne podsumowanie treści w kolejności:

  1. V3, blok 1 MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, blok 4 KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, blok 1 MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. Wersja 2, SHA2-256.

Zobacz długość z prefiksem sekwencji podpisów z prefiksami o długości w schemacie podpisu plików APK w wersji 3.

proces weryfikacji pakietu APK wersja 4
Rysunek 1. Proces weryfikacji plików APK w wersji 4

Weryfikacja i testowanie

Sprawdź implementację, korzystając z testów jednostek funkcji i CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Testowanie formatu podpisu

Aby przetestować format podpisu, ustaw w środowisku programistycznym i przeprowadź te testy ręczne:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Testowanie formatu podpisu za pomocą pakietu Android SDK (ADB i apksigner)

Aby przetestować format podpisu za pomocą pakietu Android SDK, skonfiguruj środowisko programistyczne i upewnij się, że została zakończona IncFS. Następnie uruchom kompilację na docelowym urządzeniu fizycznym lub emulatorze. Potrzebujesz aby wygenerować lub uzyskać dotychczasowy plik APK, a następnie utworzyć klucz podpisywania debugowania. Na koniec podpisz i zainstaluj pakiet apk w formacie podpisu w wersji 4. z folderu Build-tools.

Podpis

$ ./apksigner sign --ks debug.keystore game.apk

Zainstaluj

$ ./adb install game.apk

Gdzie można znaleźć te testy?

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java