Android 11 unterstützt ein Streaming-kompatibles Signaturschema mit dem APK Signature Scheme v4. Die v4-Signatur basiert auf dem über alle Bytes der APK berechneten Merkle-Hash-Baum. Es folgt genau der Struktur des fs-verity- Hash-Baums (zum Beispiel das Auffüllen des Salzes mit Nullen und das 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 an Bytes wie ihre sizeof()
, ohne implizite Auffüllung oder Ausrichtung.
Unten finden Sie eine Hilfsstruktur zur Vereinfachung der 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
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
wird aus dem v3-Signaturblock der APK oder, falls nicht vorhanden, aus dem v2-Block entnommen (siehe apk_digest ).
Um einen signature
zu erstellen und zu überprüfen, müssen die folgenden Daten in einen Binärblob 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; };
-
merkle_tree
ist der gesamte Merkle-Baum der APK, berechnet wie in der fs-verity -Dokumentation beschrieben.
Produzenten und Konsumenten
Das Android SDK-Tool apksigner
generiert jetzt die v4-Signaturdatei, wenn Sie es mit Standardparametern ausführen. Die v4-Signatur 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 vorhanden ist, wenn der Befehl adb install --incremental
ausgeführt wird
Außerdem wird standardmäßig die .idsig-Datei verwendet, um eine inkrementelle Installation zu versuchen, und es wird auf eine reguläre Installation zurückgegriffen, wenn diese 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 gesamter Blob an incfs übergeben. Incfs extrahiert Root-Hash aus dem Blob.
Wenn die Installationssitzung festgeschrieben wird, führt PackageManagerService einen ioctl aus, um den signing_info-Blob von incfs abzurufen, analysiert ihn und überprüft die Signatur.
Von der inkrementellen Data Loader-Komponente wird erwartet, dass sie den Merkle-Baum-Teil der Signatur über die native API des Data Loaders streamt.
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 Inhalts-Digest 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.
Siehe längenpräfixierte Sequenz von längenpräfixierten Signaturen in APK Signature Scheme v3.
![APK-Validierungsprozess v4](https://source.android.google.cn/static/docs/security/images/apk-validation-process-v4.png?authuser=6&hl=de)
Validierung und Tests
Validieren Sie die Implementierung mithilfe von Feature Unit Tests und CTS.
-
CtsIncrementalInstallHostTestCases
- /android/cts/hostsidetests/incrementalinstall
Testen des Signaturformats
Um das Signaturformat zu testen, richten Sie 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. Anschließend flashen Sie 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. Signieren und installieren Sie abschließend die APK mit dem v4-Signaturformat aus dem Build-Tools-Ordner.
Zeichen
$ ./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