アプリへの署名

アプリに署名することで、開発者は複雑なインターフェースや権限を作成しなくてもアプリの作成者を特定し、アプリを更新できます。Android プラットフォームで実行されるすべてのアプリには、デベロッパーによる署名が必要です。署名なしでアプリのインストールを試みた場合は、Google Play または Android デバイスのパッケージ インストーラによってインストールが拒否されます。

Google Play におけるアプリ署名は、Google が保証するデベロッパーの信頼性と、デベロッパーが保証するアプリの信頼性をつなぐ役割を果たします。開発されたアプリが、修正などが施されないまま Android デバイスにインストールされることをデベロッパーに対して証明します。アプリの動作についてデベロッパーの責任を明確にする役目もあります。

Android では、アプリをアプリ サンドボックスに配置するときにまず行われるのがアプリへの署名です。署名済みのアプリ証明書は、どのユーザー ID がどのアプリに関連付けられているかを定義するもので、ユーザー ID に応じて異なるアプリが実行されます。アプリ署名を使用すれば、明確に定義された IPC を介さない限り、アプリ間のアクセスができないようになります。

アプリ(APK ファイル)を Android デバイスにインストールすると、パッケージ マネージャーによって APK がその APK に含まれる証明書で適切に署名されているかどうかの検証が行われます。証明書(正確には証明書の公開鍵)がデバイス上の他の APK の署名に使用されるキーと一致する場合、新しい APK には、同様に署名された他の APK と UID を共有することをマニフェストで指定するというオプションがあります。

アプリは、サードパーティ(OEM、オペレータ、代替マーケター)が署名するか、自己署名されます。Android は、外部の支援や許可を必要とすることなくデベロッパーが生成できる、自己署名証明書を使用したコード署名を提供します。アプリについては、認証局の署名は必要はありません。Android では現在、アプリ証明書の CA 認証確認を行っていません。

アプリは、署名保護レベルでセキュリティ権限を宣言することもできます。これにより、同一の鍵で署名されたアプリのみにアクセスを制限し、異なる UID とアプリ サンドボックスを維持できます。同じデベロッパーの鍵で署名された 2 つ以上のアプリについては、共有 UID をマニフェストで宣言できる共有 UID 機能を通じて、共有アプリ サンドボックスとの密接な関係性が保たれます。

APK 署名方式

Android では、次の 3 つのアプリ署名方式がサポートされています。

互換性を高めるには、最初に v1、次に v2、その次に v3 というように、すべてのスキームでアプリに署名します。Android 7.0 以降のデバイスでは、v1 スキームのみで署名されたアプリと比べて、v2 以降のスキームで署名されたアプリではインストールにかかる時間が短くなります。古い Android プラットフォームでは v2 以降の署名が無視されるため、アプリに v1 署名を含める必要があります。

JAR 署名(v1 スキーム)

APK 署名は、初期の Android から導入されていました。APK 署名は、署名付きの JAR に基づいています。このスキームの使用方法について詳しくは、アプリの署名に関する Android Studio のドキュメントをご覧ください。

v1 署名では、ZIP メタデータなどの APK の一部は保護されません。APK 検証ツールは、信頼されていない(検証されていない)大量のデータ構造を検証し、署名されていないデータは破棄する必要があります。これにより、攻撃対象領域が増大します。さらに、APK 検証ツールは圧縮されたエントリをすべて解凍する必要があるため、時間とメモリを多く消費します。こうした問題に対処するため、Android 7.0 では APK 署名スキーム v2 が導入されました。

APK 署名スキーム v2 および v3(v2 以降のスキーム)

Android 7.0 以降のデバイスは、APK 署名スキーム v2(v2 スキーム)以降をサポートしています(Android 9 では v2 スキームが v3 に更新され、署名ブロックには追加の情報が含まれますが、それ以外の機能は以前と同様です)。APK のコンテンツはハッシュ化して署名され、その後 APK 署名ブロックが APK に挿入されます。アプリへの v2 以降のスキームの適用に関して詳しくは、APK 署名スキーム v2 をご覧ください。

検証中、v2 以降のスキームは APK ファイルを blob として扱い、ファイル全体で署名の確認を行います。ZIP メタデータの変更を含む APK への変更を行うと、APK 署名が無効になります。この形式での APK 検証はきわめて高速で、より多くのクラスに関する不正な変更を検出できます。

この新しい形式は下位互換性を持つため、新しい署名形式で署名された APK であっても、APK が v1 で署名されている限りは、古い Android デバイスにインストールできます(APK に追加された追加データは無視されます)。

APK 署名検証プロセス

図 1: APK 署名検証プロセス

APK のファイル全体のハッシュは、APK 署名ブロックに格納された v2 以降の署名に照らし合わせて検証されます。ハッシュには、v2 以降の署名を含む APK 署名ブロックを除くすべての内容が含まれています。APK 署名ブロックの外部で APK を変更すると、v2 以降の APK の署名が無効になります。また、v2 以降の署名が削除された APK も拒否されます。これは、v1 署名によって APK が v2 で署名されたことが指定されており、Android 7.0 以降では v1 署名を使用した APK の検証が拒否されるためです。

APK 署名検証プロセスについて詳しくは、APK 署名スキーム v2 の検証のセクションをご覧ください。