Vérification complète de la transparence des APK des services système Google

Cette page décrit différentes méthodes pour vous assurer que l'APK installé sur votre appareil Android correspond à la réclamation effectuée dans le modèle de demandeur. Pour ce faire, vous devez extraire l'APK en question de votre appareil, vérifier son intégrité de code et effectuer une preuve d'inclusion de journal sur l'artefact extrait.

Procédure de validation

Un journal de transparence est implémenté avec un arbre de Merkle composé de hachages. Un nœud feuille contient des données, et un nœud parent contient le hachage de ses enfants.

Fondamentalement, deux calculs sont effectués sur l'arbre Merkle pour vérifier la propriété inviolable des journaux de transparence: la preuve d'inclusion et la preuve de cohérence. Le premier prouve que le journal inclut une entrée correspondant à une version d'APK particulière. L'entrée de journal inclut un hachage, qui est le récapitulatif SHA256 du jeton de signature de code sous la forme d'un jeton Web JSON (JWT), qui peut être obtenu à partir des APK correspondants. Ce dernier prouve que lorsque de nouvelles entrées sont ajoutées à l'arborescence, le nouveau point de contrôle est (cryptographiquement) cohérent avec la version précédente de l'arborescence.

Pour valider un APK couvert, effectuez un test de preuve d'inclusion basé sur un point de contrôle témoin. Notez que nous prévoyons d'intégrer ce journal à un réseau de témoins public à l'aide d'un protocole de témoin standardisé. Cela fournit un point de contrôle témoin, qui garantit la cohérence du journal.

Si vous souhaitez vous assurer que l'APK que vous avez sur votre appareil est conforme à la réclamation formulée dans le modèle du demandeur, consultez l'article ci-dessous.

Preuve d'inclusion

Un utilisateur Android peut vérifier qu'un APK couvert sur son appareil figure dans le journal en extrayant d'abord l'APK et ses métadonnées pertinentes, puis en comparant le hachage racine recalculé avec le hachage racine contenu dans le point de contrôle publié. Si elles correspondent, l'utilisateur Android peut bénéficier de certaines protections décrites dans le modèle de menace.

Vérifier l'inclusion d'un APK dans le journal

Comme décrit précédemment, la liste des APK actuellement couverts est disponible sur la page Vue d'ensemble.

Conditions préalables à la validation

Avant de vérifier que l'APK que vous venez d'extraire de votre appareil est conforme à notre réclamation, vous devez installer les outils suivants à partir d'un ordinateur connecté au réseau.

Android Debug Bridge (ADB)

ADB est un outil qui communique avec un appareil Android, disponible sur le site Web d'Android SDK Platform Tools.

bundletool

bundletool est un outil utilisé pour créer un Android App Bundle (AAB). Il peut également être utilisé pour convertir un AAB en APK pouvant être installés sur des appareils. Vous pouvez le télécharger sur GitHub.

Androguard

Androguard est un ensemble d'outils qui permet d'analyser les APK. Vous pouvez le télécharger et l'installer sur le site Web d'Androguard.

Outil de validation de la preuve d'inclusion

Il s'agit d'un module Go que nous avons publié dans un dépôt Git du Projet Android Open Source (AOSP) nommé avb. Il peut interroger le journal de transparence de l'APK des services système Google et indiquer si un package est inclus dans le journal. Vous trouverez un exemple d'utilisation dans une section ultérieure.

Pour télécharger cet outil, vous devez d'abord cloner le dépôt avb.

computer:~$ git clone https://android.googlesource.com/platform/external/avb

Le code source du vérificateur se trouve dans tools/transparency/verify dans le dépôt avb.

Créer une charge utile pour la validation

Pour vérifier que l'APK que vous avez extrait de votre appareil conformément à nos revendications est bien le même, vous devez créer une charge utile de journal à partir des informations dérivées de l'APK.

Avant de commencer, assurez-vous que adb peut être utilisé sur votre appareil en activant le débogage adb sur votre appareil.

Recherchez ensuite l'emplacement de l'APK sur votre appareil. Pour les besoins de ce guide, nous utiliserons l'APK Android System Key Verifier (com.google.android.contactkeys) comme exemple.

computer:~$ adb shell pm list packages -f | grep contactkeys
package:/data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk=com.google.android.contactkeys

Si l'APK Android System Key Verifier est installé sur votre appareil, la commande ci-dessus renvoie un chemin d'accès indiquant l'emplacement de l'installation sur votre appareil. Sinon, aucun résultat ne s'affichera.

Ensuite, téléchargez l'APK depuis votre appareil Android sur l'ordinateur sur lequel vous travaillez à l'aide de cette commande (notez que l'emplacement réel et le nom de fichier de l'APK sur votre appareil peuvent varier):

computer:~$ mkdir -p /tmp/testdir && cd /tmp/testdir
computer:/tmp/testdir$ adb pull /data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk ./contactkeys_candidate.apk

Pour obtenir et vérifier le nom de package de l'APK que vous venez de télécharger, vous devez d'abord décompresser l'APK, car un APK est en fin de compte un type de fichier ZIP spécial.

computer:/tmp/testdir$ mkdir extracted && unzip contactkeys_candidate.apk -d extracted/

Cette étape décompresse tous les fichiers qui composent l'APK. Le nom et la version du package se trouvent dans le fichier manifeste de l'APK, qui se trouve généralement dans un fichier nommé AndroidManifest.xml.

Toutefois, le fichier manifeste obtenu est au format binaire, qui n'est pas lisible par l'humain. Pour convertir le fichier XML binaire en format lisible, nous utilisons l'outil axml de la suite androguard (à installer dans la section Prérequis).

computer:/tmp/testdir$ androguard axml extracted/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1413" android:versionName="1.48.688082145" android:compileSdkVersion="35" android:compileSdkVersionCodename="VanillaIceCream" android:requiredSplitTypes="" android:splitTypes="" package="com.google.android.contactkeys" platformBuildVersionCode="35" platformBuildVersionName="VanillaIceCream">

D'après la sortie ci-dessus, nous pouvons maintenant être sûrs que le nom du package de cet APK est com.google.android.contactkeys et que le numéro de version (versionCode) est 1413.

Nous allons maintenant rechercher la signature de transparence du code dans l'APK. Il doit s'agir d'un fichier nommé code_transparency_signed.jwt contenu dans le dossier META-INF parmi les autres fichiers extraits de l'APK.

computer:/tmp/testdir$ sha256sum extracted/META-INF/code_transparency_signed.jwt
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11  code_transparency_signed.jwt

Avec cette chaîne de hachage, nous disposons désormais de toutes les informations nécessaires pour assembler une charge utile de journal selon le format décrit dans la section Contenu du journal. Dans cet exemple, une charge utile de journal correspondante doit se présenter comme suit:

1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11
SHA256(Signed Code Transparency JWT)
com.google.android.contactkeys
1143

Notez également le caractère de nouvelle ligne après la version du package.

Vous pouvez enregistrer le contenu dans un fichier, par exemple payload.txt. Cela vous sera utile lorsque vous effectuerez le test de preuve d'inclusion plus tard.

Vérifier l'authenticité de la signature du code APK

Nous devons maintenant vérifier l'authenticité du jeton de signature de code intégré à l'APK. Pour ce faire, nous utilisons bundletool et la clé publique de la paire de clés qui a été utilisée pour la signer en premier lieu. Ils sont publiés dans chaque section des APK respectifs. En supposant que vous ayez enregistré le certificat de clé publique (par exemple, pour Android System Key Verifier) dans un fichier nommé signing_cert_pubkey.pem, suivez le guide ci-dessous pour effectuer la vérification de la signature de code.

Vous devez d'abord créer une archive ZIP et y ajouter l'APK candidat.

computer:/tmp/testdir$ zip -u test.zip contactkeys_candidate.apk
        zip warning: test.zip not found or empty
  adding: contactkeys_candidate.apk (deflated 58%)

computer:/tmp/testdir$ file test.zip
test.zip: Zip archive data, at least v2.0 to extract, compression method=deflate

Nous sommes maintenant prêts à utiliser la commande check-transparency de bundletool pour vérifier si la signature de code intégrée à l'APK candidat correspond à celle publiée.

computer:/tmp/testdir$ java -jar BUNDLETOOL_INSTALL_PATH/bundletool-all-version.jar check-transparency \
  --mode=apk \
  --apk-zip=test.zip \
  --transparency-key-certificate=signing_cert_pubkey.pem

APK signature is valid. SHA-256 fingerprint of the apk signing key certificate (must be compared with the developer's public key manually): D9 E1 73 5B 2A 39 51 27 3A 87 35 B7 66 9E F1 9E F5 3A F1 C1 27 5C BA 31 39 3C 18 40 8B 03 79 D0
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.

Vous devez vous assurer que la sortie de la commande ci-dessus indique que la signature de transparence du code et la transparence du code sont validées. Si ce n'est pas le cas, par exemple, si une sortie telle que Code transparency verification failed because the provided public key certificate does not match the transparency file s'affiche, cela signifie que l'intégrité du code de l'APK en question peut être compromise et que vous ne devez pas faire confiance à l'APK. N'oubliez pas de vérifier que vous les comparez au bon certificat de clé publique. Sinon, si tout le reste est correct, cela signifie que l'authenticité de la signature de code est validée pour l'APK que vous validez.

Vérifier l'inclusion du package (preuve d'inclusion)

À l'aide de la charge utile que vous avez créée plus tôt, vous êtes maintenant prêt à tester si le package en question a été inclus dans le journal de transparence.

Un outil de preuve d'inclusion a été publié dans le dépôt avb du projet Android Open Source. Pour l'exécuter:

computer:external/avb/tools/transparency/verify$ PAYLOAD_PATH=PATH_TO_PAYLOAD_DIR/payload.txt
computer:external/avb/tools/transparency/verify$ go build cmd/verifier/verifier.go
computer:external/avb/tools/transparency/verify$ ./verifier --payload_path=${PAYLOAD_PATH} --log_type=google_system_apk

Le vérificateur utilise le point de contrôle correspondant et le contenu du journal (disponible dans le répertoire de cartes) pour vérifier que la charge utile de votre APK figure dans le journal de transparence, et qu'elle est bien publiée par Google.

Le résultat de la commande est écrit dans stdout:

  • OK. inclusion check success! si le code du package est inclus dans le journal ;
  • FAILURE si ce n'est pas le cas.