Schema di firma dell'APK v4

Android 11 supporta uno schema di firma compatibile con lo streaming con l'APK Schema di firma v4. La firma della versione 4 è basata sull'albero di hash di Merkle calcolato su tutti i byte dell'APK. Segue esattamente la struttura dell'albero di hash fs-verity (ad esempio, zero-spaziatura interna) il sale e una spaziatura interna pari a zero per l'ultimo blocco). Android 11 memorizza la firma in un file separato, <apk name>.apk.idsigUna firma v4 richiede una firma complementare v2 o v3.

Formato file

Tutti i campi numerici sono in Littendian. Tutti i campi occupano esattamente il numero di byte come sizeof(), senza spaziatura interna implicita allineamento aggiunto.

Di seguito è riportato uno struct helper per semplificare 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 l'albero dell'hash generata + l'hash principale:

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 è il seguente struct:

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 recuperato dal blocco di firma v3 dell'APK o, in caso contrario dal blocco v2 (vedi apk_digest)

Per creare e verificare un codice signature deve essere serializzato i seguenti dati nel BLOB binario e passarli al algoritmo di firma / 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;
};
  1. merkle_tree è l'intero albero di Merkle dell'APK, calcolato come descritto nella documentazione fs-verity.
di Gemini Advanced.

Produttori e consumatori

apksigner Lo strumento SDK Android ora genera il file della firma v4 se lo esegui con parametri predefiniti. La firma v4 può essere disattivata allo stesso modo degli altri schemi di firma. Può anche verificare se la firma v4 è valida.

adb richiede che il file .apk.idsig sia presente accanto ad .apk quando esegui il comando adb install --incremental
Utilizzerà anche il file .idsig per provare l'installazione incrementale predefinita e, se mancante o mancante, ritorneranno a un'installazione standard non valido.

Quando viene creata una sessione di installazione, la nuova API di installazione di flussi di dati nel campo PackageInstaller accetta lo strip la firma v4 come argomento separato quando si aggiunge un file alla sessione. A questo punto, signing_info viene passato agli incf come una l'intero blob. Incfs estrae l'hash radice dal blob.

Quando viene eseguito il commit della sessione di installazione, PackageManagerService esegue un ioctl per recuperare il blob sign_info dagli incfs, lo analizza e verifica la firma.

Il componente Caricatore dati incrementale dovrebbe trasmettere in streaming la parte dell'albero Merkle della firma tramite l'API nativa di caricamento dei dati.
Comando shell di servizio package install-incremental accetta il file della firma v4 rimosso codificato come base64 come parametro per ogni file aggiunto. L'albero di Merkle corrispondente deve essere inviato nell'interfaccia stdin.

digest apk

apk_digest è la prima sintesi disponibile dei contenuti, ordinata:

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

Vedi con prefisso lunghezza sequenza di firme con prefisso lungo nello schema di firma dell'APK v3.

procedura di convalida apk v4
Figura 1: procedura di convalida dell'APK v4

Convalida e test

Convalida l'implementazione utilizzando i test delle unità di funzionalità e CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Test del formato della firma

Per testare il formato della firma, configura un ambiente di sviluppo ed esegui i seguenti test manuali:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Test del formato della firma con l'SDK per Android (ADB e apksigner)

Per testare il formato della firma con l'SDK Android, configura un ambiente di sviluppo e di aver completato l'implementazione IncFS. Quindi esegui il flashing della build su un emulatore o un dispositivo fisico di destinazione. Ti servono per generare o ottenere un APK esistente e quindi creare una chiave di firma di debug. Infine, firma e installa l'APK con formato di firma v4. dalla cartella build-tools.

Firma

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

Installa

$ ./adb install game.apk

Dove è possibile trovare questi test?

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