Google System Services APK の透明性に関する完全な検証

このページでは、 Android デバイスにインストールされている APK が、 請求者モデルで行われた主張に対応していることを確認するさまざまな方法について説明します。これには、問題の APK をデバイスから取得し、コードの整合性を確認して、抽出したアーティファクトでログ包含証明を実行することが含まれます。

検証プロセス

透明性ログは、ハッシュで構成される Merkle ツリーを使用して実装されます。 リーフノードにはデータが含まれ、親ノードには子のハッシュが含まれます。

基本的に、透明性ログの改ざん防止プロパティを検証するために、Merkle ツリーで 2 つの計算(包含証明と整合性証明)が実行されます。前者は、ログに特定の APK バージョンに対応するエントリが含まれていることを証明します。ログエントリには、対応する APK から取得できる JSON Web Token(JWT)形式のコード署名トークンの SHA256 ダイジェストであるハッシュが含まれます。後者は、新しいエントリがツリーに追加されたときに、新しいチェックポイントがツリーの以前のバージョンと(暗号的に)整合していることを証明します。

対象の APK を検証するには、確認済みのチェックポイントに基づいて包含証明テストを実施します。 このログは、標準化された 確認プロトコルを使用して、公開確認ネットワークと統合する予定です。 これにより、ログの整合性を保証する確認済みのチェックポイントが提供されます。

デバイスにインストールされている APK が請求者モデルで行われた主張に準拠していることを確認する場合は、以下の説明をご覧ください。

包含証明

Android ユーザーは、デバイス上の対象の APK がログに含まれていることを確認できます。まず、APK とその関連メタデータを抽出し、再計算したルートハッシュを公開されたチェックポイントに含まれるルートハッシュと比較します。 一致する場合、Android ユーザーは脅威モデルで説明されている保護の一部を保証できます。

ログで APK の包含を確認する方法

前述のとおり、現在対象となっている APK のリストは、 概要ページに記載されています。

検証の前提条件

アーティファクト(ファームウェアまたは APK)が主張に準拠していることを検証する前に、ネットワークに接続されたパソコンで次のツールが使用可能であることを確認してください。 検証対象によっては、すべてが必要ない場合もあります。

Golang

検証ツール は Go で記述されています。ビルドするには、Go サイトから Go 1.24 以降をインストールします。 Go サイトからインストールします。

Android Debug Bridge(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 Asset Packaging Tool)は、Android アプリのリソースのコンパイルとパッケージ化に使用されるビルドツールです。 Android SDK Build Tools バージョン 26.0.2 以降でスタンドアロン ツールとして提供されています。

bundletool

bundletool は、Android App Bundle(AAB)のビルドに使用されるツールです。APK コード署名の検証にも使用できます。 GitHub からダウンロードできます。

wget または curl

wgetcurl は、インターネットからファイルを取得またはダウンロードするために使用できるツールです。 検証スクリプトでこれらのツールが使用される可能性があるため、いずれかのツールがインストールされていることを確認してください。

Avbtool

avbtool は、ファクトリー イメージの VBMeta ダイジェストの計算と バイナリの検証に使用されます。 (包含証明検証ツールのセクションで説明したように)avb リポジトリのクローンを作成すると、クローンされた avb ディレクトリ内に avbtool.py があります。このディレクトリを $PATH 環境変数に追加する必要があります。

computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL

Fbpacktool

fbpacktool は、Pixel の個々のコンポーネントを解凍するために使用される Python スクリプトです。 bootloader.img。 APK を検証する場合は必要ありません。 このツールは、avbtool.py が検証に必要なイメージを検出できるようにするため、重要です。

このツールを使用するには、次の 3 つの 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 から派生した情報からログペイロードを作成する必要があります。

開始する前に、デバイスで 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 がデバイスにインストールされている場合、上記のコマンドは、デバイスにインストールされている場所を示すパスを返します。 それ以外の場合は、出力は表示されません

次に、このコマンドを使用して、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 内でコード透明性署名を検索します。これは、APK から抽出された他のファイルの中から META-INF フォルダに含まれる code_transparency_signed.jwt という名前のファイルです。

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 System Key Verifierなど) を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

bundletoolcheck-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_1p_code

検証ツールは、対応するチェックポイントとログの内容( タイル ディレクトリにあります)を使用して、APK ペイロードが透明性 ログに含まれていることを確認し、Google によって公開されていることを検証します。

コマンドの出力は stdout に書き込まれます。

  • パッケージのコードがログに含まれている場合は OK. inclusion check success!
  • 含まれていない場合は FAILURE