本頁說明各種方法,確保安裝在 Android 裝置上的 APK 符合著作權人模型中的聲明。這包括從裝置中提取有問題的 APK、檢查程式碼完整性,以及對擷取的構件執行記錄納入證明。
驗證程序
透明化記錄是透過由雜湊組成的默克爾樹實作。 葉節點包含資料,父項節點則包含子項的雜湊值。
基本上,系統會在 Merkle 樹狀結構上執行兩項運算,以驗證透明記錄的防竄改特性:納入證明和一致性證明。前者可證明記錄包含與特定 APK 版本相應的項目。記錄檔項目包含雜湊,也就是程式碼簽章權杖的 SHA256 摘要,格式為 JSON Web Token (JWT),可從對應的 APK 取得。後者證明在樹狀結構中新增項目時,新的檢查點會與樹狀結構的先前版本 (以密碼編譯方式) 保持一致。
如要驗證受保護的 APK,請根據見證的檢查點執行納入證明測試。請注意,我們計畫使用標準化的見證協定,將這項記錄與公開見證網路整合。這會提供經過見證的檢查點,確保記錄的一致性。
如要確認裝置上的 APK 是否符合聲明人模型中的聲明,請參閱下文。
收錄證明
Android 使用者可以先擷取裝置上受保護的 APK 及其相關中繼資料,然後比較重新計算的根雜湊值與已發布檢查點中包含的根雜湊值,確認 APK 是否在記錄中。如果相符,Android 使用者就能獲得威脅模型中所述的保護措施。
如何驗證 APK 是否已納入記錄
如前所述,您可以在總覽頁面中查看目前涵蓋的 APK 清單。
驗證的必要條件
繼續驗證剛從裝置擷取的 APK 是否符合我們的聲明前,請先從連網電腦安裝下列工具。
Android Debug Bridge (ADB)
ADB 是與 Android 裝置通訊的工具,可從 Android SDK 平台工具網站取得。
AAPT2
AAPT2 (Android 資產封裝工具) 是用於編譯及封裝 Android 應用程式資源的建構工具。在 Android SDK Build Tools 26.0.2 以上版本中,AAPT2 是獨立工具。
bundletool
bundletool 是用於建構 Android App Bundle (AAB) 的工具。也可以用來將 AAB 轉換為可安裝在裝置上的 APK。可從 GitHub 下載。
Inclusion Proof 驗證器
這是我們在 Android 開放原始碼計畫 (AOSP) 內名為 avb 的 Git 存放區中發布的 Go 模組。這項工具可以查詢 Google 系統服務 APK 透明度記錄,並輸出套件是否包含在記錄中。如需使用方式範例,請參閱後續章節。
如要下載這項工具,請先複製 avb 存放區。
computer:~$ git clone https://android.googlesource.com/platform/external/avb
驗證器的原始碼位於 avb 存放區的 tools/transparency/verify 中。
建構驗證酬載
如要驗證您根據我們的聲明從裝置擷取的 APK,必須從 APK 衍生資訊建構記錄檔酬載。
開始前,請先在裝置上啟用 ADB 偵錯,確認裝置可以使用 adb。
然後找出 APK 在裝置上的安裝位置。在本指南中,我們將使用 Android System Key Verifier APK (com.google.android.contactkeys) 做為工作範例。
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
如果裝置上已安裝 Android System Key Verifier APK,上述指令會傳回路徑,指出該 APK 在裝置上的安裝位置。否則不會看到任何輸出內容。
接著,使用下列指令,將 Android 裝置上的 APK 下載到您使用的電腦 (請注意,裝置上的實際位置和 APK 檔案名稱可能有所不同):
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
如要取得並驗證剛下載的 APK 套件名稱,請先解壓縮 APK,因為 APK 最終是特殊類型的 ZIP 檔案。
computer:/tmp/testdir$ mkdir extracted && unzip contactkeys_candidate.apk -d extracted/
這個步驟會解壓縮組成 APK 的所有檔案。您可以在 APK 的資訊清單中找到套件名稱和版本,通常位於名為 AndroidManifest.xml 的檔案中。
不過,取得的資訊清單檔案是二進位格式,無法供人閱讀。如要將二進位 XML 轉換為使用者可理解的格式,我們會使用先前安裝的 aapt2 工具 (如必要條件一節所述)。
computer:/tmp/testdir$ aapt2 dump badging ./contactkeys_candidate.apk
package: name='com.google.android.contactkeys' versionCode='7805' versionName='1.219.791156583' platformBuildVersionName='Baklava' platformBuildVersionCode='36' compileSdkVersion='36' compileSdkVersionCodename='Baklava'
從上述輸出內容,我們現在可以確定這個 APK 的套件名稱是 com.google.android.contactkeys,版本號碼 (versionCode) 是 1413。
現在,我們將在 APK 中搜尋程式碼透明性簽章。這個檔案應命名為 code_transparency_signed.jwt,並位於 META-INF 資料夾中,與從 APK 擷取的其他檔案放在一起。
computer:/tmp/testdir$ sha256sum extracted/META-INF/code_transparency_signed.jwt
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11 code_transparency_signed.jwt
有了這個雜湊字串,我們現在就擁有所有必要資訊,可根據記錄內容部分說明的格式,組合出記錄酬載。在本例中,對應的記錄酬載應如下所示:
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11
SHA256(Signed Code Transparency JWT)
com.google.android.contactkeys
1143
另請注意套件版本後方的新行字元。
你可以將內容儲存到檔案,例如 payload.txt。稍後進行納入證明測試時,這項資訊會派上用場。
驗證 APK 程式碼簽章的真實性
現在,我們應該驗證 APK 內嵌程式碼簽章權杖的真實性。為此,我們會使用 bundletool,以及最初用於簽署的金鑰組公開金鑰。這些檔案會發布在各個 APK 的相應區段中。假設您已將公開金鑰憑證 (例如 Android 系統金鑰驗證器) 儲存到名為 signing_cert_pubkey.pem 的檔案,請按照下列指南執行程式碼簽章驗證。
首先,您應建立 ZIP 封存檔,然後將候選 APK 新增至 ZIP 封存檔。
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
我們現在可以使用 bundletool 的 check-transparency 指令,驗證候選 APK 內嵌的程式碼簽章是否與發布的簽章相符。
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.
請確認上述指令的輸出內容指出「程式碼透明性簽章」和「程式碼透明性」都已通過驗證。如果不是,例如您看到 Code transparency verification failed because the provided public key
certificate does not match the transparency file 等輸出內容,表示有問題的 APK 程式碼完整性可能遭到破壞,因此不應信任該 APK。請務必仔細檢查,確認您是根據正確的公開金鑰憑證驗證這些權杖。如果其他一切正常,則表示您驗證的 APK 程式碼簽章已通過驗證。
驗證套件是否納入 (納入證明)
使用先前建構的酬載,您現在可以測試相關套件是否已納入透明度記錄。
Android 開放原始碼計畫的 avb 存放區已發布納入證明工具。如要執行這項指令,請按照下列步驟操作:
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
驗證者會使用對應的檢查點和記錄內容 (位於圖塊目錄),確認 APK 酬載位於透明度記錄中,並驗證 APK 確實是由 Google 發布。
指令輸出內容會寫入 stdout:
OK. inclusion check success!如果記錄中包含套件的程式碼,FAILURE。