Android 11 obsługuje schemat podpisywania zgodny z transmisją strumieniową ze schematem podpisu APK v4. Sygnatura v4 jest oparta na drzewie skrótów Merkle obliczonym dla wszystkich bajtów APK. Jest on dokładnie zgodny ze strukturą drzewa mieszającego fs-verity (na przykład dopełnienie zerami soli i dopełnienie zerami ostatniego bloku). Android 11 przechowuje podpis w osobnym pliku, <apk name>.apk.idsig
Podpis w wersji 4 wymaga podpisu uzupełniającego w wersji 2 lub 3 .
Format pliku
Wszystkie pola numeryczne są w little endian. Wszystkie pola zajmują dokładnie taką liczbę bajtów, jak ich sizeof()
, nie dodano niejawnego wypełnienia ani wyrównania.
Poniżej znajduje się struktura pomocnicza upraszczająca definicje.
template <class SizeT> struct sized_bytes { SizeT size; byte bytes[size]; };
Główna zawartość 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 };
hashing_info
to parametry używane do generowania drzewa skrótów + skrót główny:
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
to następująca struktura:
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; };
-
apk_digest
jest pobierany z bloku podpisywania APK v3 lub, jeśli go nie ma, z bloku v2 (patrz apk_digest )
Aby utworzyć i zweryfikować kod signature
należy zserializować następujące dane do binarnego obiektu blob i przekazać je do algorytmu podpisującego/weryfikującego jako dane podpisane :
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; };
-
merkle_tree
to całe drzewo Merkle APK, obliczone zgodnie z opisem w dokumentacji fs-verity .
Producenci i konsumenci
apksigner
Android SDK generuje teraz plik podpisu v4, jeśli uruchomisz go z domyślnymi parametrami. Podpisywanie v4 można wyłączyć w taki sam sposób, jak inne schematy podpisywania. Może również zweryfikować poprawność podpisu v4.
adb
oczekuje, że plik .apk.idsig będzie obecny obok pliku .apk podczas uruchamiania polecenia adb install --incremental
Wykorzysta również plik .idsig do domyślnego wypróbowania instalacji przyrostowej i powróci do zwykłej instalacji, jeśli jej brakuje lub jest ona nieprawidłowa.
Po utworzeniu sesji instalacyjnej nowy interfejs API do przesyłania strumieniowego instalacji w PackageInstaller
akceptuje obnażony podpis v4 jako oddzielny argument podczas dodawania pliku do sesji. W tym momencie signing_info
jest przekazywane do incfs jako cały obiekt blob. Incfs wyodrębnia hasz korzeniowy z plamy.
Podczas zatwierdzania sesji instalacyjnej PackageManagerService wykonuje ioctl, aby pobrać obiekt blob signing_info z incfs, analizuje go i weryfikuje podpis.
Oczekuje się, że komponent Incremental Data Loader będzie przesyłał strumieniowo część podpisu z drzewa Merkle za pośrednictwem natywnego interfejsu API modułu ładującego dane.
Polecenie powłoki usługi package
install-incremental
akceptuje usunięty plik podpisu v4 zakodowany jako base64 jako parametr dla każdego dodanego pliku. Odpowiednie drzewo Merkle musi zostać przesłane do stdin
polecenia.
apk_digest
apk_digest
to pierwsze dostępne podsumowanie treści w kolejności:
- V3, blok 1MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
- V3, blok 4KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
- V3, blok 1MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
- V2, SHA2-512,
- V2, SHA2-256.
Zobacz sekwencję podpisów z przedrostkiem długości w schemacie podpisu APK w wersji 3.

Walidacja i testowanie
Sprawdź poprawność implementacji za pomocą testów jednostkowych funkcji i CTS.
-
CtsIncrementalInstallHostTestCases
- /android/cts/hostsidetests/incrementalinstall
Testowanie formatu podpisu
Aby przetestować format podpisu, skonfiguruj środowisko programistyczne i uruchom następujące testy ręczne:
$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest
Testowanie formatu podpisu za pomocą Android SDK (ADB i apksigner)
Aby przetestować format podpisu za pomocą Android SDK, skonfiguruj środowisko programistyczne i upewnij się, że implementacja IncFS została zakończona . Następnie sflashuj kompilację na docelowym urządzeniu fizycznym lub emulatorze. Musisz wygenerować lub uzyskać istniejący plik APK, a następnie utworzyć klucz podpisywania debugowania . Na koniec podpisz i zainstaluj apk w formacie podpisu v4 z folderu narzędzi do budowania.
Podpisać
$ ./apksigner sign --ks debug.keystore game.apk
zainstalować
$ ./adb install game.apk
Gdzie można znaleźć te testy?
/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java