この記事は ソフトウェア エンジニア、Shawn Willden による Android Developers Blog の記事 "Keystore Key Attestation" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
アプリのデベロッパーは、認証や暗号化用の暗号鍵を使う方法として何年も前から Android のキーストアを利用できます。キーストアによって、アプリのプロセス空間からキーマテリアルを分離できます。そのため、意図せずにアプリでユーザーに鍵が公開され、フィッシングに使われたり、他のチャンネルによって漏洩したり、アプリの欠陥を通して鍵が危険にさらされることはなくなります。多くの端末では、キーストアの鍵はハードウェア ベースのセキュリティで保護されており、セキュア ハードウェア上に格納されています。キーマテリアルは完全に Android システムの外にあるため、たとえ Linux カーネルに欠陥があったとしても、キーマテリアルが漏洩することはありません。セキュア ハードウェアとは、大半の Android 端末では Linux カーネルと Android ユーザー空間からハードウェアによって強制的に隔離されているメイン CPU の特殊なモードを指しています。端末によっては、保護された別のマイクロプロセッサを利用しているものもあります。
Android では、アプリで指定されたキーストアの鍵がセキュア ハードウェアに格納されているかどうかを判断できる API が提供されています。しかし、オペレーティング システムに欠陥がある場合、これらの API は信頼できないかもしれません。鍵の構成証明は、非対称な鍵がセキュア ハードウェアに格納されており、Android OS の欠陥から保護されていることを端末のセキュア ハードウェアによって検証する方法です。
キーストアは Android 4.0 で初めて導入され、鍵がユーザーのパスコードで暗号化されるようになりました。Android 4.1 では、端末のセキュア ハードウェアを使うためのインフラストラクチャが追加されました。
Android 6.0 までは、キーストアでは RSA と ECDSA がサポートされていましたが、Android 6.0 でキーストアが大幅に強化され、AES と HMAC がサポートされるようになりました。さらに、RSA パディング1や AES ブロック チェーン2モードなどの暗号操作に欠かせない要素もセキュア ハードウェアに移動しました。
Android 6.0 では、特定の鍵の用途を制限する機能もキーストアに追加されています。適用される制限のうち、もっともわかりやすいのが ユーザー認証バインドです。これは、鍵の用途をユーザーのパスコード(PIN、パターン、パスワード)や指紋に「バインド」するものです。パスコード認証バインドでは、アプリのデベロッパーはタイムアウトを秒数で指定できます。ユーザーが最後にパスコードを入力してから指定された時間以上が経過すると、セキュア ハードウェアがその鍵を利用するすべてのリクエストを拒否します。指紋にバインドされた鍵では、鍵を使うたびに新しいユーザー認証が要求されます。
その他の技術的な制限は、Android 6.0 以上の鍵にも適用されます。特に重要なのは、鍵の作成やインポートの時点で、鍵を利用できる暗号学的な目的(暗号化、復号化、署名、検証)、パディングやブロックモード、ダイジェスト、初期化ベクトルのエントロピーのソース(nonce)、その他の暗号操作の詳細を指定する必要がある点です。指定された情報は永久的かつ暗号学的にキーマテリアルにバインドされるため、キーストアはその鍵を別の方法に使うことを許可しません。そのため、攻撃者がアプリやシステムを制御したとしても、鍵を悪用することはできません。攻撃を防ぐため、デベロッパーは鍵にできるだけ狭い範囲の用途を指定する必要があります。
Android キーストアで特に重要な変更は、Android 7.0 で導入されました。Android 7.0 以上がインストールされた状態でリリースされ、安全なロック画面が搭載される新端末では、セキュア ハードウェアに加え、ハードウェア ベースのパスコード認証およびキーストアの鍵が必須になりました。セキュア ハードウェアのサポートは Android 7.0 より前から広がっていましたが、これは今後数年間で一般的になるでしょう。
Android 8.0 では、Google Play がインストールされた状態で出荷されるすべての新端末で、鍵の構成証明が必須になりました。
銀行の顧客に対して、残高、取引記録、請求支払いシステムにアクセスできるアプリを開発する場合を考えてみましょう。セキュリティは重要です。スマートフォンを拾った人がそのユーザーの銀行口座にアクセスできるようにしたいとは誰も思いません。それを防ぐアプローチの 1 つは、ユーザーのウェブサイトのパスワードを使う方法です。しかし、ウェブサイトでは、小さなタッチスクリーンでの入力に不向きな長く複雑なパスワードが求められることが多いため、不便に感じるユーザーが多いでしょう。
Android のキーストアを使うと、256 ビット ECDSA 鍵などの非対称な認証鍵を生成できます。各ユーザーは、一度だけ複雑なウェブのパスワードを使ってログインし、銀行の顧客口座データベースに公開鍵を登録できます。そして、ユーザーがアプリを開くたびに、ECDSA 鍵を使ったチャレンジ レスポンス認証プロトコルを実行します。さらに、鍵を認証用にバインドすれば、ユーザーはアプリを開くたびにロック画面のパスコードや指紋を使って認証できるようになります。これにより、スマートフォンでシンプルで便利な認証メカニズムが実現できます。
鍵はセキュアハードウェア内に格納されているため、攻撃者が Android の欠陥を悪用して鍵を抽出することはできません。
アプリのデベロッパーが鍵の構成証明を利用すると、アプリがリクエストした ECDSA 鍵が実際にセキュア ハードウェア内に格納されているかをサーバー側で検証することができます。アプリ自身が構成証明を使ってもあまり意味がありませんので注意してください。Android OS に欠陥がなく、信頼できる場合は、6.0 で導入された KeyInfoクラスを使うだけで鍵がセキュア ハードウェアに格納されているかどうかを検出できます。欠陥がある場合、この API も端末上で行う構成証明の検証結果も信頼できません。
なお、鍵の構成証明は SafetyNet 構成証明とは異なるものです。考え方は同じですが、これらは異なる場所で行われる異なるものに対する構成証明です。キーストアの鍵の構成証明は、暗号鍵がセキュア ハードウェアに格納されており、特別な特徴を持っていることを証明するものです。SafetyNet 構成証明は、端末が本物(エミュレータでない)で既知のソフトウェアが実行されていることを証明するものです。SafetyNet は、内部的にキーストアの鍵の構成証明を利用しています。端末の整合性について知りたい場合はこれを使うようにし、鍵がセキュア ハードウェアに格納されていることを確認したい場合は鍵の構成証明を使います。
詳細やサンプルコードについては、developer.android.com の鍵の構成証明のトレーニング記事をご覧ください。
Reviewed by Yuichi Araki - Developer Relations Team
アプリのデベロッパーは、認証や暗号化用の暗号鍵を使う方法として何年も前から Android のキーストアを利用できます。キーストアによって、アプリのプロセス空間からキーマテリアルを分離できます。そのため、意図せずにアプリでユーザーに鍵が公開され、フィッシングに使われたり、他のチャンネルによって漏洩したり、アプリの欠陥を通して鍵が危険にさらされることはなくなります。多くの端末では、キーストアの鍵はハードウェア ベースのセキュリティで保護されており、セキュア ハードウェア上に格納されています。キーマテリアルは完全に Android システムの外にあるため、たとえ Linux カーネルに欠陥があったとしても、キーマテリアルが漏洩することはありません。セキュア ハードウェアとは、大半の Android 端末では Linux カーネルと Android ユーザー空間からハードウェアによって強制的に隔離されているメイン CPU の特殊なモードを指しています。端末によっては、保護された別のマイクロプロセッサを利用しているものもあります。
Android では、アプリで指定されたキーストアの鍵がセキュア ハードウェアに格納されているかどうかを判断できる API が提供されています。しかし、オペレーティング システムに欠陥がある場合、これらの API は信頼できないかもしれません。鍵の構成証明は、非対称な鍵がセキュア ハードウェアに格納されており、Android OS の欠陥から保護されていることを端末のセキュア ハードウェアによって検証する方法です。
キーストアの歴史
キーストアは Android 4.0 で初めて導入され、鍵がユーザーのパスコードで暗号化されるようになりました。Android 4.1 では、端末のセキュア ハードウェアを使うためのインフラストラクチャが追加されました。
Android 6.0 までは、キーストアでは RSA と ECDSA がサポートされていましたが、Android 6.0 でキーストアが大幅に強化され、AES と HMAC がサポートされるようになりました。さらに、RSA パディング1や AES ブロック チェーン2モードなどの暗号操作に欠かせない要素もセキュア ハードウェアに移動しました。
Android 6.0 では、特定の鍵の用途を制限する機能もキーストアに追加されています。適用される制限のうち、もっともわかりやすいのが ユーザー認証バインドです。これは、鍵の用途をユーザーのパスコード(PIN、パターン、パスワード)や指紋に「バインド」するものです。パスコード認証バインドでは、アプリのデベロッパーはタイムアウトを秒数で指定できます。ユーザーが最後にパスコードを入力してから指定された時間以上が経過すると、セキュア ハードウェアがその鍵を利用するすべてのリクエストを拒否します。指紋にバインドされた鍵では、鍵を使うたびに新しいユーザー認証が要求されます。
その他の技術的な制限は、Android 6.0 以上の鍵にも適用されます。特に重要なのは、鍵の作成やインポートの時点で、鍵を利用できる暗号学的な目的(暗号化、復号化、署名、検証)、パディングやブロックモード、ダイジェスト、初期化ベクトルのエントロピーのソース(nonce)、その他の暗号操作の詳細を指定する必要がある点です。指定された情報は永久的かつ暗号学的にキーマテリアルにバインドされるため、キーストアはその鍵を別の方法に使うことを許可しません。そのため、攻撃者がアプリやシステムを制御したとしても、鍵を悪用することはできません。攻撃を防ぐため、デベロッパーは鍵にできるだけ狭い範囲の用途を指定する必要があります。
Android キーストアで特に重要な変更は、Android 7.0 で導入されました。Android 7.0 以上がインストールされた状態でリリースされ、安全なロック画面が搭載される新端末では、セキュア ハードウェアに加え、ハードウェア ベースのパスコード認証およびキーストアの鍵が必須になりました。セキュア ハードウェアのサポートは Android 7.0 より前から広がっていましたが、これは今後数年間で一般的になるでしょう。
Android 8.0 では、Google Play がインストールされた状態で出荷されるすべての新端末で、鍵の構成証明が必須になりました。
鍵の構成証明を使用する理由
銀行の顧客に対して、残高、取引記録、請求支払いシステムにアクセスできるアプリを開発する場合を考えてみましょう。セキュリティは重要です。スマートフォンを拾った人がそのユーザーの銀行口座にアクセスできるようにしたいとは誰も思いません。それを防ぐアプローチの 1 つは、ユーザーのウェブサイトのパスワードを使う方法です。しかし、ウェブサイトでは、小さなタッチスクリーンでの入力に不向きな長く複雑なパスワードが求められることが多いため、不便に感じるユーザーが多いでしょう。
Android のキーストアを使うと、256 ビット ECDSA 鍵などの非対称な認証鍵を生成できます。各ユーザーは、一度だけ複雑なウェブのパスワードを使ってログインし、銀行の顧客口座データベースに公開鍵を登録できます。そして、ユーザーがアプリを開くたびに、ECDSA 鍵を使ったチャレンジ レスポンス認証プロトコルを実行します。さらに、鍵を認証用にバインドすれば、ユーザーはアプリを開くたびにロック画面のパスコードや指紋を使って認証できるようになります。これにより、スマートフォンでシンプルで便利な認証メカニズムが実現できます。
鍵はセキュアハードウェア内に格納されているため、攻撃者が Android の欠陥を悪用して鍵を抽出することはできません。
アプリのデベロッパーが鍵の構成証明を利用すると、アプリがリクエストした ECDSA 鍵が実際にセキュア ハードウェア内に格納されているかをサーバー側で検証することができます。アプリ自身が構成証明を使ってもあまり意味がありませんので注意してください。Android OS に欠陥がなく、信頼できる場合は、6.0 で導入された KeyInfoクラスを使うだけで鍵がセキュア ハードウェアに格納されているかどうかを検出できます。欠陥がある場合、この API も端末上で行う構成証明の検証結果も信頼できません。
なお、鍵の構成証明は SafetyNet 構成証明とは異なるものです。考え方は同じですが、これらは異なる場所で行われる異なるものに対する構成証明です。キーストアの鍵の構成証明は、暗号鍵がセキュア ハードウェアに格納されており、特別な特徴を持っていることを証明するものです。SafetyNet 構成証明は、端末が本物(エミュレータでない)で既知のソフトウェアが実行されていることを証明するものです。SafetyNet は、内部的にキーストアの鍵の構成証明を利用しています。端末の整合性について知りたい場合はこれを使うようにし、鍵がセキュア ハードウェアに格納されていることを確認したい場合は鍵の構成証明を使います。
詳細やサンプルコードについては、developer.android.com の鍵の構成証明のトレーニング記事をご覧ください。