APK-Signaturschema v4

Android 11 unterstützt ein Streaming-kompatibles Signaturschema mit dem APK-Signaturschema v4. Die v4-Signatur basiert auf dem Merkle-Hashbaum, der über alle Bytes der APK berechnet wird. Es folgt genau der Struktur des fs-verity-Hashbaums (z. B. Auffüllen des Salzes mit Nullen und Auffüllen des letzten Blocks mit Nullen). Android 11 speichert die Signatur in einer separaten Datei, <apk name>.apk.idsig Eine v4-Signatur erfordert eine ergänzende v2- oder v3 -Signatur.

Datei Format

Alle numerischen Felder sind in Little Endian. Alle Felder belegen genau die Anzahl von Bytes wie ihre sizeof() , keine implizite Auffüllung oder Ausrichtung hinzugefügt.

Unten ist eine Hilfsstruktur, um die Definitionen zu vereinfachen.

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-Baum-Generierung verwendet werden, + der Root-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 stammt aus dem v3-Signaturblock der APK oder, falls nicht vorhanden, aus dem v2-Block (siehe apk_digest )

Um einen signature zu erstellen und zu verifizieren, müssen die folgenden Daten in ein binäres 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 der APK, berechnet wie in der fs-verity- Dokumentation beschrieben.

Produzenten und Konsumenten

apksigner Android SDK-Tool generiert jetzt die v4-Signaturdatei, wenn Sie es mit Standardparametern ausführen. Die v4-Signierung kann auf die gleiche Weise wie die anderen Signaturschemata deaktiviert werden. Es kann auch überprüfen, ob die v4-Signatur gültig ist.

adb erwartet, dass die Datei .apk.idsig neben der .apk-Datei vorhanden ist, wenn der Befehl adb install --incremental ausgeführt wird
Es wird auch die .idsig-Datei verwenden, um standardmäßig eine inkrementelle Installation zu versuchen, und auf eine reguläre Installation zurückgreifen, wenn sie fehlt oder ungültig ist.

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

Wenn die Installationssitzung festgeschrieben wird, führt PackageManagerService ein ioctl aus, um das signing_info-Blob von incfs abzurufen, es zu analysieren und die Signatur zu überprüfen.

Es wird erwartet, dass die inkrementelle Data Loader-Komponente den Merkle-Baum-Teil der Signatur über die native Data Loader-API streamt.
Der package -Shell-Befehl install-incremental akzeptiert die entfernte v4-Signaturdatei, die als Base64 codiert ist, als Parameter für jede hinzugefügte Datei. Der entsprechende Merkle-Baum muss in die stdin des Befehls gesendet werden.

apk_digest

apk_digest ist der erste verfügbare Content Digest in der folgenden Reihenfolge:

  1. V3, 1 MB Block, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, 4-KB-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.

Siehe Sequenz mit Längenpräfix von Signaturen mit Längenpräfix in APK Signature Scheme v3.

APK-Validierungsprozess v4
Abbildung 1 : APK-Validierungsprozess v4

Validierung und Prüfung

Validieren Sie die Implementierung mit Feature Unit Tests und CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Testen des Signaturformats

Richten Sie zum Testen des Signaturformats eine Entwicklungsumgebung ein und führen Sie die folgenden manuellen Tests durch:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Testen des Signaturformats mit Android SDK (ADB und apksigner)

Um das Signaturformat mit Android SDK zu testen, richten Sie eine Entwicklungsumgebung ein und stellen Sie sicher, dass Sie die Implementierung von IncFS abgeschlossen haben. Flashen Sie dann den Build auf einem physischen Zielgerät oder Emulator. Sie müssen ein vorhandenes APK generieren oder abrufen und dann einen Debug-Signaturschlüssel erstellen . Abschließend signieren und installieren Sie die apk mit v4-Signaturformat aus dem build-tools-Ordner.

Schild

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

Installieren

$ ./adb install game.apk

Wo sind diese Tests zu finden?

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