本頁說明如何驗證 Android 裝置上安裝的 APK 或 APEX 是否與聲明人模型中的聲明相符。這個程序包括從裝置擷取 APK,並對擷取的構件執行記錄納入證明。
驗證程序
透明度記錄是透過由雜湊組成的 Merkle 樹實作。 葉節點包含資料,父項節點則包含子項的雜湊值。
兩項基本運算會驗證透明度記錄的防竄改特性:納入證明和一致性證明。納入證明會確認記錄檔是否包含特定 APK 版本的項目。這個記錄項目包含雜湊,也就是安裝在裝置上的 APK 檔案的 SHA256 摘要。 一致性證明可確保新增項目時,新的檢查點在密碼學上與樹狀結構的先前版本保持一致 (或樹狀結構未遭竄改)。本指南著重於計算納入證明程序的過程,同時依賴見證人持續對最新檢查點執行一致性證明。
如要驗證涵蓋的 APK,請針對見證的檢查點執行納入證明。請注意,我們計畫使用標準化見證協定,將這項記錄與公開見證網路整合。這項整合功能會提供見證檢查點,確保記錄檔的一致性。
如要確認裝置上的 Google 應用程式符合申請人型號中的聲明,請按照下列步驟操作。
收錄證明
如要確認裝置上受保護的 APK 是否在記錄中,請擷取 APK、計算其雜湊值,然後使用納入證明檢查該雜湊值是否存在於已發布的檢查點。如果成功提供納入證明,即可防範威脅模型中所述的風險,並確認應用程式是正當的 Google 應用程式。
如何驗證 APK 是否已納入記錄
任何聲稱是 Google 第一方應用程式的應用程式,都可以根據這個記錄進行驗證。
通過認證的必要條件
在驗證構件 (韌體或 APK) 是否符合聲明之前,請先確認連網電腦上是否備妥下列工具:視驗證目標而定,您可能不必提供所有資訊。
Golang
驗證工具是以 Go 語言編寫。如要建構該工具,請從 Go 網站安裝 Go 1.24 以上版本。
Android Debug Bridge (ADB)
ADB 工具可與 Android 裝置通訊,檢查映像檔或擷取 APK,可從 Android SDK 平台工具網站取得。
Inclusion Proof 驗證器
納入證明驗證器是 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 是用來解壓縮 Pixel bootloader.img 中個別元件的 Python 指令碼。如果您要驗證 APK,則不需要這個檔案。
這項工具非常重要,因為可讓 avbtool.py 找出驗證所需的圖片。
如要使用這項工具,請將下列三個 Python 指令碼下載到 avbtool.py 所在的目錄中,將 fbpacktool.py 設為可執行,並建立名為 fbpacktool 的符號連結到 fbpacktool.py,方便使用。
如果使用 wget:
computer:dir_to_avbtool$ wget https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool
如果使用 curl:
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.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存放區也包含 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 值表示系統已根據透明化記錄,以密碼編譯方式驗證套件,確認套件符合記錄的聲明。