Android 11 supporta uno schema di firma compatibile con lo streaming con lo schema di firma dell'APK v4. La firma v4 si basa sull'albero hash Merkle
calcolato su tutti i byte dell'APK. Lo schema segue esattamente la struttura dell'albero hash fs-verity (ad esempio, il riempimento con zeri del sale e dell'ultimo blocco). Android 11 memorizza la firma
in un file separato, <apk name>.apk.idsig. Una firma v4
richiede una firma v2 o v3 complementare.
Formato file
Tutti i campi numerici sono in formato little endian. Tutti i campi occupano esattamente il numero
di byte del relativo sizeof(), senza padding o allineamento implicito.
Il seguente struct helper semplifica le definizioni:
template <class SizeT> struct sized_bytes { SizeT size; byte bytes[size]; };
Contenuti del file principale:
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 è il parametro utilizzato per la generazione dell'albero hash
più l'hash radice:
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 è la seguente struttura:
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 viene estratto dal blocco di firma v3 dell'APK. Se questo blocco non è
presente, viene preso dal blocco v2 (vedi apk_digest).
Per creare e verificare, un codice signature deve serializzare
i seguenti dati in un blob binario e passarlo all'algoritmo
di firma e verifica come dati firmati:
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 è l'intero albero Merkle dell'APK, calcolato come descritto nella documentazione di fs-verity.
Produttori e consumatori
Lo strumento SDK Android apksigner genera il file di firma v4
se lo esegui con i parametri predefiniti. Puoi disattivare la firma v4 nello stesso modo
degli altri schemi di firma. Lo strumento può anche verificare se la firma v4 è valida.
adb prevede che il file .apk.idsig sia presente accanto all'APK quando
viene eseguito il comando adb install --incremental. adb utilizza anche il file IDSIG
per tentare l'installazione incrementale per impostazione predefinita e ripristina un'installazione normale se
il file non è presente o non è valido.
Quando viene creata una sessione di installazione, la nuova API Streaming Installation
in PackageInstaller accetta la firma v4 stripped
come argomento separato quando si aggiunge un file alla sessione.
A questo punto, signing_info viene passato a IncFS come
blob intero. IncFS estrae l'hash radice dal blob.
Quando la sessione di installazione viene eseguita, PackageManagerService esegue
una chiamata ioctl per recuperare il blob signing_info da IncFS, lo analizza
e verifica la firma.
Il componente Incremental Data Loader trasmette in streaming la parte dell'albero Merkle
della firma tramite l'API nativa del caricatore di dati. Il comando shell del servizio package install-incremental accetta il file di firma v4 eliminato codificato come Base64 come parametro per ogni file aggiunto. L'albero Merkle corrispondente deve essere inviato nel
stdin del comando.
apk_digest
apk_digest è il primo digest dei contenuti disponibile in ordine:
- V3, blocco da 1 MB, SHA2-512 (
CONTENT_DIGEST_CHUNKED_SHA512) - V3, blocco da 4 KB, SHA2-256 (
CONTENT_DIGEST_VERITY_CHUNKED_SHA256) - V3, blocco da 1 MB, SHA2-256 (
CONTENT_DIGEST_CHUNKED_SHA256) - V2, SHA2-512
- V2, SHA2-256
Consulta la sequenza con prefisso di lunghezza del firmatario con prefisso di lunghezza nello schema di firma dell'APK v3.
Convalida e test
La procedura di convalida dell'APK v4 è illustrata nella figura seguente:

Figura 1. Procedura di convalida dell'APK v4.
Convalida l'implementazione utilizzando i test delle unità delle funzionalità e CTS:
CtsIncrementalInstallHostTestCases/android/cts/hostsidetests/incrementalinstall
Testare il formato della firma
Per testare il formato della firma, configura un ambiente di build ed esegui i seguenti test manuali:
$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest
Testare il formato della firma con l'SDK Android (ADB e apksigner)
Utilizza questa procedura per testare il formato della firma con l'SDK Android:
- Configura un ambiente di build e assicurati di aver completato l'implementazione di IncFS.
- Installa la build su un emulatore o un dispositivo fisico di destinazione.
- Genera o ottieni un APK esistente, quindi crea una chiave di firma di debug.
- Firma e installa l'APK con il formato di firma v4
dalla cartella build-tools.
Firma
$ ./apksigner sign --ks debug.keystore game.apk
Installa
$ ./adb install game.apk
Dove si trovano questi test
/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java