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

本页概述了如何验证 Android 设备上安装的 APK 或 APEX 是否与声明方模型中提出的声明相符。此过程包括从设备中提取 APK,并对提取的制品执行日志包含证明。

验证流程

透明度日志是通过包含哈希值的 Merkle 树实现的。 叶节点包含数据,父节点包含其子节点的哈希值。

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

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

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

纳入证明

您可以提取 APK、计算其哈希值,并使用纳入证明来检查该哈希值是否存在于已发布的检查点中,从而验证设备上受涵盖的 APK 是否在日志中。成功的纳入证明可防范威胁模型中所述的风险,并确认相应应用是合法的 Google 应用。

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

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

验证的前提条件

在验证提取的 APK 之前,应在计算机上安装以下工具:

Android 调试桥 (ADB)

ADB 是一种与 Android 设备通信的工具,可在 Android SDK Platform Tools 网站上获取。

AAPT2

AAPT2(Android 资源打包工具)是一种用于编译和打包 Android 应用资源的构建工具。它以独立工具的形式提供,位于 Android SDK Build Tools 26.0.2 及更高版本中。

Go 语言

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

纳入证明验证器

我们在 android-binary-transparency GitHub 代码库中发布了一个名为 verifier 的 Go 模块。此工具会查询 Google 第一方 APK 透明度日志,以检查是否包含某个软件包。

如需使用此工具,请先将代码库克隆到本地计算机:

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

验证器的源代码位于 android-binary-transparency 代码库中。

构建用于验证的载荷

如需验证提取的 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 的文件。 此文件列出了每个已安装的软件包,以及一个设置为 truefalseinclusion_proof_verified 字段。值为 true 表示已针对透明度日志对软件包进行加密验证,确认其符合日志的声明。