APK-Signaturschema v4

Android 11 unterstützt ein streamingkompatibles Signaturschema mit dem APK-Signaturschema v4. Die V4-Signatur basiert auf dem Merkle-Hash-Baum, der über alle Bytes des APK berechnet wird. Er folgt genau der Struktur des fs-verity-Hashbaums (z. B. Null-Padding des Salzes und des letzten Blocks). Unter Android 11 wird die Signatur in einer separaten Datei gespeichert. <apk name>.apk.idsigEine V4-Signatur erfordert eine ergänzende V2- oder V3-Signatur.

Dateiformat

Alle numerischen Felder sind im Little-Endian-Format. Alle Felder belegen genau die Anzahl von Byte wie ihre sizeof(), es wird kein impliziter Padding oder keine implizite Ausrichtung hinzugefügt.

Unten finden Sie eine Hilfsstruktur, die die Definitionen vereinfacht.

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 sind die Parameter, die für die Hash-Baumgenerierung verwendet werden, und der Wurzel-Hash:

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 V3-Signaturblock des APK oder, falls nicht vorhanden, aus dem V2-Block übernommen (siehe apk_digest).

Zum Erstellen und Verifizieren eines signature-Codes müssen die folgenden Daten in einen Binär-Blob serialisiert und als signierte Daten an den Signatur-/Verifizierungsalgorithmus übergeben werden:

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 ist der gesamte Merkle-Baum des APK, der wie in der fs-verity-Dokumentation beschrieben berechnet wird.

Produzenten und Verbraucher

apksigner Das Android SDK-Tool generiert jetzt die V4-Signaturdatei, wenn Sie es mit den Standardparametern ausführen. Die V4-Signatur kann auf die gleiche Weise wie die anderen Signaturschemata deaktiviert werden. Außerdem kann damit geprüft werden, ob die V4-Signatur gültig ist.

adb erwartet, dass die Datei „.apk.idsig“ neben der Datei „.apk“ vorhanden ist, wenn der Befehl adb install --incremental ausgeführt wird.
Außerdem wird die Datei „.idsig“ standardmäßig für die inkrementelle Installation verwendet. Wenn sie fehlt oder ungültig ist, wird auf eine reguläre Installation zurückgegriffen.

Wenn eine Installationssitzung erstellt wird, akzeptiert die neue Streaming-Installations-API in der PackageInstaller die entfernte V4-Signatur als separates Argument, wenn der Sitzung eine Datei hinzugefügt wird. An diesem Punkt wird signing_info als ganzer Blob an incfs übergeben. Incfs extrahiert den Root-Hash aus dem Blob.

Wenn die Installationssitzung verbindlich wird, führt PackageManagerService einen ioctl aus, um den signing_info-Blob aus incfs abzurufen, ihn zu parsen und die Signatur zu überprüfen.

Die Komponente „Incremental Data Loader“ soll den Merkle-Baum-Teil der Signatur über die native API des Data Loaders streamen.Der
package-Dienst-Shellbefehl install-incremental nimmt die entfernbare V4-Signaturdatei, die als Base64 codiert ist, als Parameter für jede hinzugefügte Datei an. Der entsprechende Merkle-Baum muss an die stdin des Befehls gesendet werden.

apk_digest

apk_digest ist der erste verfügbare Inhalts-Digest in folgender Reihenfolge:

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

Weitere Informationen finden Sie im APK-Signaturschema 3 unter Abfolge von Signaturen mit Längenpräfix.

Apk-Validierungsprozess V4
Abbildung 1: APK-Validierungsprozess v4

Validierung und Tests

Validieren Sie die Implementierung mithilfe von Feature-Unit-Tests und CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Signaturformat testen

Wenn Sie das Signaturformat testen möchten, richten Sie eine Entwicklungsumgebung ein und führen Sie die folgenden manuellen Tests aus:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Signaturformat mit dem Android SDK (ADB und apksigner) testen

Wenn Sie das Signaturformat mit dem Android SDK testen möchten, richten Sie eine Entwicklungsumgebung ein und prüfen Sie, ob Sie die Implementierung von IncFS abgeschlossen haben. Flashen Sie dann das Build auf einem Zielgerät oder Emulator. Sie müssen ein APK generieren oder ein vorhandenes APK abrufen und dann einen Debug-Signaturschlüssel erstellen. Signieren und installieren Sie die APK schließlich mit dem Signaturformat v4 aus dem Ordner „build-tools“.

Unterschreiben

$ ./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