APK Signature Scheme v4

Android 11 est compatible avec un schéma de signature compatible avec le streaming avec le schéma de signature APK v4. La signature v4 est basée sur l'arborescence de hachage Merkle calculée sur tous les octets de l'APK. Il suit exactement la structure de l'arborescence de hachage fs-verity (par exemple, remplissage à zéro du sel et du dernier bloc). Android 11 stocke la signature dans un fichier distinct, <apk name>.apk.idsig. Une signature v4 nécessite une signature v2 ou v3 complémentaire.

Format de fichier

Tous les champs numériques sont au format little-endian. Tous les champs occupent exactement le nombre d'octets de leur sizeof(), sans ajout de marge intérieure ni d'alignement implicite.

Vous trouverez ci-dessous une struct d'assistance pour simplifier les définitions.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Contenu du fichier principal:

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 correspond aux paramètres utilisés pour la génération de l'arborescence de hachage et au hachage racine:

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 est la structure suivante:

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 est extrait du bloc de signature v3 de l'APK ou, si ce n'est pas le cas, du bloc v2 (voir apk_digest).

Pour créer et valider un code signature, vous devez sérialiser les données suivantes dans un blob binaire et les transmettre à l'algorithme de signature / validation en tant que données signées:

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 correspond à l'ensemble de l'arbre Merkle de l'APK, calculé comme décrit dans la documentation fs-verity.

Producteurs et consommateurs

L'outil SDK Android apksigner génère désormais le fichier de signature v4 si vous l'exécutez avec les paramètres par défaut. La signature v4 peut être désactivée de la même manière que les autres schémas de signature. Il peut également vérifier si la signature v4 est valide.

adb s'attend à ce que le fichier .apk.idsig soit présent à côté du fichier .apk lors de l'exécution de la commande adb install --incremental.
Il utilisera également le fichier .idsig pour essayer l'installation incrémentielle par défaut et utilisera une installation standard s'il est manquant ou non valide.

Lorsqu'une session d'installation est créée, la nouvelle API d'installation en streaming dans PackageInstaller accepte la signature v4 débarrassée en tant qu'argument distinct lors de l'ajout d'un fichier à la session. À ce stade, signing_info est transmis dans incfs en tant que blob complet. Incfs extrait le hachage racine du blob.

Lorsque la session d'installation est validée, PackageManagerService effectue une ioctl pour récupérer le blob signing_info à partir d'incfs, l'analyse et vérifie la signature.

Le composant Data Loader incrémentiel doit diffuser la partie de l'arbre Merkle de la signature via l'API native du chargeur de données.La commande shell de service install-incremental de
package accepte le fichier de signature v4 tronqué encodé en base64 comme paramètre pour chaque fichier ajouté. L'arbre Merkle correspondant doit être envoyé dans le stdin de la commande.

apk_digest

apk_digest est le premier récapitulatif de contenu disponible dans l'ordre suivant:

  1. V3, bloc de 1 Mo, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, bloc de 4 ko, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, bloc de 1 Mo, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. V2, SHA2-256.

Consultez la séquence de signatures avec préfixe de longueur dans le schéma de signature des fichiers APK v3.

Processus de validation de l&#39;APK V4
Figure 1: Processus de validation de l'APK v4

Validation et test

Validez l'implémentation à l'aide de tests unitaires de fonctionnalités et de CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Tester le format de la signature

Pour tester le format de signature, configurez un environnement de développement et exécutez les tests manuels suivants:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Tester le format de signature avec le SDK Android (ADB et apksigner)

Pour tester le format de signature avec le SDK Android, configurez un environnement de développement et assurez-vous d'avoir terminé l'implémentation d'IncFS. Ensuite, flashez le build sur un appareil physique ou un émulateur cible. Vous devez générer ou obtenir un APK existant, puis créer une clé de signature de débogage. Enfin, signez et installez l'APK avec le format de signature v4 à partir du dossier build-tools.

Signer

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

Installer

$ ./adb install game.apk

Où trouver ces tests ?

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