Google 产品应用透明度完整验证

本页概述了如何验证 Android 设备上安装的 APK 或 APEX 是否与 权利主张方模型中的声明一致。该过程包括从设备中提取 APK,并对提取的工件执行日志包含证明。

验证流程

透明度日志使用由哈希组成的 Merkle 树实现。 叶节点包含数据,父节点包含其子节点的哈希。

两项基本计算可验证透明度日志的防篡改属性:包含证明和一致性证明。 包含证明可确认日志包含特定 APK 版本的条目。 此日志条目包含一个哈希,该哈希是设备上安装的 APK 文件的 SHA256 摘要。 一致性证明可确保在添加新条目时,新检查点在加密方面与树的先前版本保持一致(或树未被篡改)。 在本指南中,我们将重点介绍计算包含证明的过程,同时依靠见证人针对最新检查点持续执行一致性证明。

如需验证受保护的 APK,请针对见证的检查点执行包含证明。 请注意,我们计划使用标准化 见证协议将此日志与公共见证网络集成 。 此集成将提供见证的检查点,以保证日志的一致性。

如需验证设备上的 Google 应用是否符合权利主张方模型中的声明,请按以下步骤操作。

包含证明

您可以验证设备上受保护的 APK 是否在日志中,方法是提取 APK、计算其哈希,并使用包含证明来检查该哈希是否存在于已发布的检查点中。成功的包含证明可针对威胁模型中所述的风险提供保证,确认该应用是合法的 Google 应用。

如何验证日志中是否包含 APK

任何声称是 Google 第一方应用的应用都可以根据此日志进行验证。

验证前提条件

在继续验证工件(固件或 APK)是否符合声明之前,请确保网络连接的计算机上提供以下工具。 根据验证目标,您可能不需要所有这些工具。

Golang

验证工具 是用 Go 编写的。如需构建该工具,请从 Go 网站安装 Go 1.24 或更高版本 。

Android 调试桥 (ADB)

ADB 是一种与 Android 设备通信以检查映像或 提取 APK 的工具,可在 Android SDK Platform Tools 网站上找到。

包含证明验证程序

包含证明验证程序是一个 Go 模块,用于查询透明度日志并输出工件是否包含在日志中。 它发布在 android-binary-transparency GitHub 代码库中,网址为 https://github.com/android/android-binary-transparency/tree/main

如需克隆 AOSP avb 代码库,请执行以下操作:

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

如需克隆 android-binary-transparency GitHub 代码库,请执行以下操作:

computer:~$ git clone https://github.com/android/android-binary-transparency

AAPT2

AAPT2(Android 资源打包工具)是一种构建工具,用于编译和打包 Android 应用的资源。 您可以在 Android SDK Build Tools 26.0.2 及更高版本中找到作为独立工具提供的 AAPT2。

bundletool

bundletool 是一种用于构建 Android App Bundle (AAB) 的工具。它还可用于验证 APK 代码签名。 您可以从 GitHub 下载该工具。

wget 或 curl

wget 和 curl 是可用于从互联网检索或下载文件的工具。 请务必安装其中一个工具,因为验证脚本可能依赖于这些工具。

Avbtool

avbtool 用于计算出厂映像的 VBMeta 摘要和验证 二进制文件。 克隆 avb 代码库后(如包含证明验证程序 部分所示),您可以在克隆的 avb 目录中找到 avbtool.py。 您应将此目录添加到 $PATH 环境变量中。

computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL

Fbpacktool

fbpacktool 是一个 Python 脚本,用于解压缩 Pixel 的 bootloader.img中的各个组件。 如果您要验证 APK,则不需要此脚本。 此工具非常重要,因为它可让 avbtool.py 发现验证所需的映像。

fbpacktool 需要 Python 3.6 或更高版本以及 PyYAML 软件包 (例如,python3 -m pip install pyyaml)。

如需使用此工具,您应将以下六个 Python 脚本 下载到 avbtool.py 所在的目录中, 使 fbpacktool.py 可执行, 并创建一个名为 fbpacktool 的符号链接到 fbpacktool.py,以方便使用。

如果您有 wget:

computer:dir_to_avbtool$ wget https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpacktool.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpack.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/packedstruct.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlparser.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlserializer.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/yamlparser.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

如果您有 curl:

computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpacktool.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpack.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/packedstruct.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlparser.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlserializer.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/yamlparser.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

OpenSSL

openssl 有助于在验证工作流中使用终端执行各种加密 操作。 请确保它已安装在您的系统上。 您可以在终端中运行以下命令并确保返回的结果不为空,以进行检查:

computer:~$ which openssl
/usr/bin/openssl

构建用于验证的载荷

如需验证提取的 APK,您必须使用从 APK 本身派生的信息构建日志载荷。

在开始之前,请在设备上启用 USB 调试,以允许adb 连接。

接下来,在设备上找到已安装的 APK。本指南使用 Google Play 服务 APK (com.google.android.gms) 作为工作示例。

adb shell pm path com.google.android.gms

您应看到类似于以下内容的输出:

computer:~$ adb shell pm path com.google.android.gms
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/base.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_CronetDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteLoader_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteModulesA_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteModulesC_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_GoogleCertificates_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_MapsDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_MeasurementDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_config.en.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_config.xxhdpi.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_maps_core_dynamite_ondemand.apk

此输出表明,您的设备上为 com.google.android.gms 安装了一个基本 APK 和多个拆分 APK。 拆分 APK 的确切数量因设备的配置而异。 每个拆分 APK 都与基本 APK 共享相同的软件包名称和版本代码。

使用以下命令将列出的 APK 从 Android 设备下载到计算机(请注意,实际文件路径可能会有所不同):

mkdir -p /tmp/testdir/gms && cd /tmp/testdir/gms && \
adb shell pm path com.google.android.gms | cut -d':' -f2 | tr -d '\r' | xargs -n1 adb pull

如需验证下载的 APK 的软件包名称和版本,您需要 检查其 清单 (AndroidManifest.xml)。

由于 APK 内的清单采用二进制格式,因此请使用 aapt2 工具 (在 前提条件 步骤中安装)直接从 APK 中提取和读取 信息:

computer:/tmp/testdir/gms$ aapt2 dump badging ./base.apk
package: name='com.google.android.gms' versionCode='260834035' versionName='26.08.34 (260400-876566425)' platformBuildVersionName='Baklava' platformBuildVersionCode='36' compileSdkVersion='36' compileSdkVersionCodename='Baklava'
minSdkVersion:'35'
targetSdkVersion:'36'
...

您应重复此步骤以获取相关信息,直到您已考虑设备上安装的所有拆分 APK。

输出确认 APK 的软件包名称为 com.google.android.gms,其版本号 (versionCode) 为 260834035。

接下来,计算每个 APK 的加密哈希:

computer:/tmp/testdir/gms$ sha256sum *.apk
66aa2d7b9752cdd61065b55c8e16739d8367fa18a0f1c8c84122369f86958f1a  base.apk
c20754aee886cc55a9de91ee15c623c59d94ad22b7e435a1a48afc43cf1a106c  split_config.en.apk
68c09b63a1262e0d34020c139bc77deff3c32bd2b01177abac64790a62fb3be6  split_config.xxhdpi.apk
cd746820c27babd855fa5daea6fabcdf7b44abf3060bc547adc4219212410af0  split_CronetDynamite_installtime.apk
512ee48b60fdb0787a17f84a7dc448fdbf885b2b86a9cb50525d4c22d561b0f1  split_DynamiteLoader_installtime.apk
9e0c74bdc75c50c80d4e2e580a7eda6b8391423ab1161645f41ec6cadc07d678  split_DynamiteModulesA_installtime.apk
955780ac01f59b98bd9be12968f3824ad71b762620f7bf223c569c1a6ab7056c  split_DynamiteModulesC_installtime.apk
34c4a2e32d31554d55fc1519e2cfc3ed5027a090fb29b54cfc99f42d1da43bc5  split_GoogleCertificates_installtime.apk
475e18dde92472cde9d8300c082b6dc269613db03398bcd9d1987dff3e68f7b5  split_maps_core_dynamite_ondemand.apk
f83faf40f08bc13f4879302e01c08c863ca2304b4b4e7c9eaf8cd1e869bb6573  split_MapsDynamite_installtime.apk
ec6d854ddda6cd1ba2ba7af2d9fdf4f28c5c78be8713c64521c785429296738c  split_MeasurementDynamite_installtime.apk

现在,您已拥有构建日志载荷所需的所有信息,格式 如日志内容部分所述。从结果中选择一个哈希作为示例(您应验证每个拆分 APK 的哈希),日志载荷如下所示:

66aa2d7b9752cdd61065b55c8e16739d8367fa18a0f1c8c84122369f86958f1a
SHA256(APK)
com.google.android.gms
260834035

请确保在文件末尾添加换行符。将此内容保存到文件(例如 payload.txt)中,以便稍后与 verifier 工具一起使用。

验证软件包包含情况(包含证明)

构建载荷后,您现在可以检查软件包是否包含在透明度日志中。从您之前克隆的 android-binary-transparency 代码库构建包含证明工具:

go build cmd/verifier/verifier.go

这应会在该目录中生成一个名为 verifier 的可执行文件。 运行验证程序,提供载荷的路径并指定日志类型:

computer:android-binary-transparency$ PAYLOAD_PATH=PATH_TO_PAYLOAD_DIR/payload.txt
computer:android-binary-transparency$ ./verifier --payload_path=${PAYLOAD_PATH} --log_type=google_1p_apk

验证程序使用检查点和日志内容(来自 图块目录)来检查您的 APK 载荷是否在透明度日志中, 以确认该载荷是由 Google 发布的。

该命令输出到 stderr:

  • 如果软件包包含在日志中,则输出 OK. inclusion check success!。
  • 如果软件包未包含在日志中,则输出 FAILURE。

自动验证设备中的所有软件包

鉴于设备上可能预安装了许多 Google 应用,因此逐个枚举每个应用并单独执行包含证明可能会很麻烦。

我们提供了另一个名为 Uraniborg 的自动化工具,该工具可以检测和衡量设备上当前安装的所有软件包。 它会将其输出直接馈送到 verifier 工具中,让您只需一步即可发现和验证设备上所有应用的透明度。

如需使用此自动化工作流,请确保您的 Android 设备通过 ADB 连接到计算机。Uraniborg 源代码也包含在 android-binary-transparency 代码库中。

运行位于 scripts/python 目录中的 automate_observation.py 脚本:

python3 automate_observation.py --pull-all-apks --perform_inclusion_proof_check --verifier_path <path_to_verifier_executable>

脚本完成后,您应看到类似于以下内容的输出:

INFO:automate_observation.py:main(858): SUCCESS! Hubble was successfully deployed and executed on connected device ABCDEFGHN01234.
INFO:automate_observation.py:main(860): Hubble output files can be found at: /Users/user/home/src/android-binary-transparency/uraniborg/scripts/python/results/google/lynx/lynx:16/BP4A.260105.004.E1/14587043:user/release-keys/001

前往脚本指示的输出目录。 在其中找到名为 packages_with_inclusion_proof_signal.txt 的文件。 此文件列出了每个已安装的软件包,以及一个设置为 true 或 false 的 inclusion_proof_verified 字段。 true 值表示已针对透明度日志对软件包进行加密验证,确认其符合日志的声明。