Android 11 unterstützt ein Streaming-kompatibles Signaturschema mit dem APK-Signaturschema v4. Die v4-Signatur basiert auf dem Merkle-Hash-Baum, der über alle Bytes des APK berechnet wird. Das Schema folgt genau der Struktur des fs-verity-Hash-Baums (z. B. Auffüllen des Salt mit Nullen und Auffüllen des letzten Blocks mit Nullen). Unter Android 11 wird die Signatur in einer separaten Datei gespeichert: <apk name>.apk.idsig. Für eine v4-Signatur ist eine ergänzende v2- oder v3-Signatur erforderlich.
Dateiformat
Alle numerischen Felder sind im Little-Endian-Format. Alle Felder belegen genau die Anzahl von Bytes wie ihr sizeof(), ohne implizites Padding oder Ausrichtung.
Die folgende Hilfsstruktur vereinfacht die Definitionen:
template <class SizeT> struct sized_bytes { SizeT size; byte bytes[size]; };
Inhalt der Hauptdatei:
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 ist der Parameter, der für die Generierung des Hash-Baums sowie für den Stamm-Hash verwendet wird:
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 ist die folgende 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;
};apk_digest wird aus dem Signierungsblock v3 des APK übernommen. Wenn dieser Block nicht vorhanden ist, wird er aus dem v2-Block übernommen (siehe apk_digest).
Zum Erstellen und Bestätigen muss ein signature-Code die folgenden Daten in einen binären Blob serialisieren und als signierte Daten an den Signier- und Bestätigungsalgorithmus übergeben:
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 ist der gesamte Merkle-Baum des APK, der wie in der fs-verity-Dokumentation beschrieben berechnet wird.
Ersteller und Nutzer
Das Android SDK-Tool apksigner generiert die Signaturdatei für Version 4, wenn Sie es mit Standardparametern ausführen. Sie können die v4-Signierung auf dieselbe Weise wie die anderen Signierungsschemas deaktivieren. Das Tool kann auch prüfen, ob die v4-Signatur gültig ist.
adb erwartet, dass sich die Datei .apk.idsig neben dem APK befindet, wenn der Befehl adb install --incremental ausgeführt wird. adb verwendet die IDSIG-Datei auch, um standardmäßig eine inkrementelle Installation zu versuchen, und greift auf eine reguläre Installation zurück, wenn sie fehlt oder ungültig ist.
Wenn eine Installationssitzung erstellt wird, akzeptiert die neue Streaming-Installations-API in PackageInstaller die stripped-Signatur der Version 4 als separates Argument, wenn eine Datei der Sitzung hinzugefügt wird.
An diesem Punkt wird signing_info als vollständiger Blob an IncFS übergeben. IncFS extrahiert den Stamm-Hash aus dem Blob.
Wenn die Installationssitzung übernommen wird, ruft PackageManagerService mit ioctl das signing_info-Blob von IncFS ab, parst es und prüft die Signatur.
Die Komponente „Incremental Data Loader“ streamt den Merkle-Baumteil der Signatur über die native API des Datenloaders. Der package-Dienstshellbefehl install-incremental akzeptiert die gekürzte V4-Signaturdatei, die als Base64 codiert ist, als Parameter für jede hinzugefügte Datei. Der entsprechende Merkle-Baum muss in den stdin des Befehls gesendet werden.
apk_digest
apk_digest ist die erste verfügbare Inhaltsübersicht in der Reihenfolge:
- V3, 1 MB-Block, SHA2-512 (
CONTENT_DIGEST_CHUNKED_SHA512) - V3, 4 KB-Block, SHA2-256 (
CONTENT_DIGEST_VERITY_CHUNKED_SHA256) - V3, 1 MB-Block, SHA2-256 (
CONTENT_DIGEST_CHUNKED_SHA256) - V2, SHA2-512
- V2, SHA2-256
Weitere Informationen finden Sie unter length-prefixed sequence of length-prefixed signer im APK-Signaturschema v3.
Validierung und Tests
Der APK-Validierungsprozess v4 wird in der folgenden Abbildung veranschaulicht:

Abbildung 1: APK-Validierungsprozess v4.
Implementierung mit Funktions-Unittests und CTS validieren:
CtsIncrementalInstallHostTestCases/android/cts/hostsidetests/incrementalinstall
Signaturformat testen
Um das Signaturformat zu testen, richten Sie eine Build-Umgebung ein und führen Sie die folgenden manuellen Tests aus:
$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest
Signaturformat mit dem Android SDK testen (ADB und apksigner)
So testen Sie das Signaturformat mit dem Android SDK:
- Richten Sie eine Build-Umgebung ein und stellen Sie sicher, dass Sie die Implementierung von IncFS abgeschlossen haben.
- Spiele den Build auf ein physisches Zielgerät oder einen Emulator.
- Generieren Sie ein APK oder verwenden Sie ein vorhandenes APK und erstellen Sie dann einen Debug-Signaturschlüssel.
- Signieren und installieren Sie das APK mit dem Signaturformat v4 aus dem Ordner „build-tools“.
Sign
$ ./apksigner sign --ks debug.keystore game.apk
Installieren
$ ./adb install game.apk
Wo finde ich diese Tests?
/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java