本页概述了如何验证 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 值表示已针对透明度日志对软件包进行加密验证,确认其符合日志的声明。