APK 署名スキーム v3.1

概要

Android 13 は、既存の APK 署名スキーム v3 の改良版である APK 署名スキーム v3.1 をサポートしています。v3.1 スキームでは、APK 署名スキーム v3 のローテーションに関する既知の問題の一部が解決されています。特に、v3.1 署名スキームは SDK バージョンのターゲット設定をサポートしているため、プラットフォームの今後のリリースをローテーションの対象にできます。

v3.1 署名スキームでは、Android 12 以前では認識されないブロック ID が使用されます。したがって、プラットフォームは次のような署名者の動作を適用します。

  • Android 13 以降を搭載したデバイスは、v3.1 ブロック内のローテーションされた署名者を使用します。
  • それより前のバージョンの Android を搭載したデバイスは、ローテーションされた署名者を無視し、代わりに v3 ブロック内の元の署名者を使用します。

署名鍵をまだローテーションしていないアプリの場合、追加のアクションは不要です。アプリがローテーションの実行を選択するたびに、システムはデフォルトで v3.1 署名スキームを適用します。

v3.1 署名ブロック

v3.1 署名ブロックの内容は v3 署名ブロックと同じですが、新しいブロック ID を使用することで、これらの署名は Android 13 以降を搭載したデバイスでのみ認識されます。 これにより、v3 署名ブロック内での APK の署名には元の署名者を使用し、v3.1 署名ブロック内ではローテーションされた署名者を使用できるため、アプリはマルチ ターゲット APK を考慮する必要なく、署名鍵を安全にローテーションできます。また、これによりプラットフォームは、v3.1 署名を検証する際に、v3 署名ブロックの既存のすべての確認コードを再利用できるようになります。

デフォルトでは、apksig ライブラリは、ローテーションされた鍵とリネージが署名設定で指定された場合、常に v3.1 署名ブロックを使用します。アプリの minSdkVersion が Android 13 より小さく、ローテーションされた鍵が使用されている場合は、v3 署名ブロック内の APK に署名できるように、元の署名鍵も指定する必要があります。これは、APK が Android 9 より前のバージョンを対象にしている場合に元の署名者が必要になる現在の動作と類似しています。

特定の SDK バージョン以降の鍵のローテーションを対象にできるよう、apksig ライブラリは、ローテーションの最小 SDK バージョンを設定できる新しい API を公開します。ローテーションをサポートする最小バージョンとして Android 13 より前の SDK バージョンを指定する場合、元の v3 ブロックが使用されます。v3.1 署名ブロックは、ローテーションの最小 SDK バージョンが Android 13 以降に設定され、ローテーションが実行されている場合にのみ使用されます。v3 署名ブロックには、ローテーションの最小 SDK バージョン保護の新しい属性が追加されます。

APK にリネージを含む rotation-min-sdk-version の値 v3 署名ブロック v3.1 署名ブロック
× デフォルトまたは任意の値(以下 x 元の署名者で署名、Android 9 以降が対象 なし
デフォルト 元の署名者で署名、Android 9~12L が対象 ローテーションされた署名者で署名、Android 13 以降が対象
x < 33(Android 13) ローテーションされた署名者で署名、Android 9 以降が対象 なし
x >= 33(Android 13) 元の署名者で署名、Android 9 - (x-1) が対象 ローテーションされた署名者で署名、x+ が対象

ローテーションに関する問題

以下のローテーション関連の問題は、プラットフォーム内で解決されています。

Android 12 の修正

  • プラットフォームがリクエスト元のアプリに署名権限を付与するのは、そのアプリの現在の署名者がリネージ内にある場合か、他のアプリの現在の署名者である場合のみです。これにより、2 つのアプリが署名鍵のベスト プラクティスに従って異なる署名鍵にローテーションすると、リクエスト元のアプリに署名権限を付与できなくなります。
  • 署名リネージ内の以前の鍵にロールバック機能がなければ、署名鍵をローテーションしたばかりの APK をプラットフォームの APK ロールバック機能でロールバックすることはできませんでした。しかし、ロールバック機能では、新しいパッケージ アップデートに以前の署名鍵で署名し、ローテーションされた鍵をロールバックすることができるため、ローテーションの目的が損なわれます。
  • APK がローテーションされた鍵のみで署名された後、リネージ内の元の鍵およびローテーションされた鍵で署名された APK で更新された場合、Android 11 以前を搭載したデバイスでは、リネージ内にローテーションされた鍵のみが表示されます。

Android 11 の修正

  • PackageManager#checkSignatures が、2 つのパッケージの元の署名鍵をチェックするよう適切に更新されませんでした。 これにより、元の署名鍵を使用するインストルメンテーション APK とローテーションされた署名鍵とを使用するアプリのインストルメンテーションが破損しました。
  • sharedUserId 内のパッケージは署名リネージを共有します。 更新された署名リネージを備えたアプリが sharedUiserId 内でインストールまたは更新されると、sharedUserId の共有リネージがそのアプリのリネージに置き換えられます(つまり、アプリの署名リネージが A -> B で、アプリが sharedUserId 内で更新されリネージが B -> C となると、sharedUserId リネージは B -> C に置き換えられます)。同様に、リネージ内の以前の署名者の機能は、署名リネージが変更されない限り更新できませんでした。

v4 の統合

v4 署名スキームでは、apksigner に指定された署名設定を使用します。ローテーション用に複数の署名設定が指定されている場合は、最新のローテーションされた署名設定を使用します。v3.1 導入前は、v3 には最新のローテーションされた署名設定のみが含まれていたため、v4 はその設定をそのまま使用できました。これにより、v4 署名スキームは、SigningInfo でローテーションされた署名鍵を使用して、ローテーションをサポートすることができました。v4 の SigningInfo には完全な署名リネージは含まれませんが、v3 署名ブロックから取得することができ、プラットフォームが任意の署名クエリのリネージにアクセスできるようにします。 指定された rotation-min-sdk-version でローテーションをターゲットにするために v3.1 が使用されている場合、汎用 v3 設定には、元の署名設定と最新のローテーションされた署名設定の両方が含まれます。 v3.1 ブロックの各署名設定のための追加の署名情報ブロックを含む、v4 署名スキームの拡張機能が作成されました。

検証

v3.1 の実装をテストするには、cts/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java CTS テストを実行します。

テストの詳細については、v3 の検証セクションをご覧ください。