Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

データをより安全に取り扱うAndroid Jetpack の一部)。

セキュリティ ライブラリでは、保存データの読み取りと書き込みに加え、キーの作成と検証に関連するセキュリティに関するおすすめの方法の実装が提供されます。

このライブラリでは、ビルダー パターンを使用して、以下のセキュリティ レベルで安全なデフォルト設定を使用できます。

  • 高度な暗号化と優れたパフォーマンスを両立する強力なセキュリティ。このセキュリティ レベルは、銀行アプリやチャットアプリなどの一般向けアプリ、証明書失効チェックを行う企業向けアプリに適しています。
  • 最高セキュリティ。このセキュリティ レベルは、キーへのアクセスにハードウェア格納型キーストアとユーザー操作を必要とするアプリに適しています。

このガイドでは、セキュリティ ライブラリの推奨セキュリティ設定の利用方法のほか、ファイルに保存されている暗号化されたデータと共有設定を簡単かつ安全に読み書きする方法を説明します。

キーの管理

セキュリティ ライブラリは、キー管理に 2 部構成のシステムを使用します。

  • ファイルまたは共有設定データを暗号化するための、1 つ以上のキーを含むキーセット。キーセット自体は SharedPreferences に格納されます。

  • すべてのキーセットを暗号化するマスターキー。このキーは Android キーストア システムを使用して保存されます。

ライブラリに含まれるクラス

セキュリティ ライブラリに含まれる以下のクラスを使用すると、データをより安全に保存できます。

EncryptedFile

FileInputStreamFileOutputStream のカスタム実装を使って、アプリによるストリーミング読み取り操作とストリーミング書き込み操作のセキュリティを強化できます。

ファイル ストリームの安全な読み取り操作と書き込み操作を実現するため、セキュリティ ライブラリではストリーミング認証付き暗号(AEAD)プリミティブを使用します。このプリミティブの詳細は、GitHub の Tink ライブラリのドキュメントをご覧ください。

EncryptedSharedPreferences

SharedPreferences クラスをラップし、2 つの方式を使用してキーと値を自動的に暗号化します。

  • キーは、暗号化された状態でも検索できるように、決定性暗号化アルゴリズムを使用して暗号化されます。
  • は、AES-256 GCM を使用して暗号化されます。これは非決定性です。

以下のセクションでは、これらのクラスを使用して、ファイルと共有設定に一般的な操作を行う方法を示します。

ファイルを読み取る

次のコード スニペットは、EncryptedFile を使用して、ファイルの内容をより安全に読み取る方法を示しています。

Kotlin

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

val context = applicationContext
val fileToRead = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    File(DIRECTORY, fileToRead),
    context,
    masterKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val inputStream = encryptedFile.openFileInput()
val byteArrayOutputStream = ByteArrayOutputStream()
var nextByte: Int = inputStream.read()
while (nextByte != -1) {
    byteArrayOutputStream.write(nextByte)
    nextByte = inputStream.read()
}

val plaintext: ByteArray = byteArrayOutputStream.toByteArray()

Java

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC;
String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec);

Context context = getApplicationContext();
String fileToRead = "my_sensitive_data.txt";
EncryptedFile encryptedFile = new EncryptedFile.Builder(
        new File(DIRECTORY, fileToRead),
        context,
        masterKeyAlias,
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();

InputStream inputStream = encryptedFile.openFileInput();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int nextByte = inputStream.read();
while (nextByte != -1) {
    byteArrayOutputStream.write(nextByte);
    nextByte = inputStream.read();
}

byte[] plaintext = byteArrayOutputStream.toByteArray();

ファイルを書き込む

次のコード スニペットは、EncryptedFile を使用して、ファイルの内容をより安全に書き込む方法を示しています。

Kotlin

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val fileToWrite = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    File(DIRECTORY, fileToWrite),
    context,
    masterKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val fileContent = "MY SUPER-SECRET INFORMATION"
        .toByteArray(StandardCharsets.UTF_8))
encryptedFile.openFileOutput().apply {
    write(fileContent)
    flush()
    close()
}

Java

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC;
String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec);

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
String fileToWrite = "my_sensitive_data.txt";
EncryptedFile encryptedFile = new EncryptedFile.Builder(
        new File(DIRECTORY, fileToWrite),
        context,
        masterKeyAlias,
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();

byte[] fileContent = "MY SUPER-SECRET INFORMATION"
        .getBytes(StandardCharsets.UTF_8);
OutputStream outputStream = encryptedFile.openFileOutput();
outputStream.write(fileContent);
outputStream.flush();
outputStream.close();

さらに強化されたセキュリティが必要なユースケースでは、次の手順を実行します。

  1. KeyGenParameterSpec.Builder オブジェクトを作成して、truesetUserAuthenticationRequired() に、0 より大きい値を setUserAuthenticationValidityDurationSeconds() に渡します。
  2. createConfirmDeviceCredentialIntent() を使用して、ユーザーに認証情報の入力を求めます。鍵を使用するためのユーザー認証のリクエスト方法についてご確認ください。

  3. onActivityResult() をオーバーライドして、確認済み認証情報のコールバックを取得します。

詳細については、キー使用を承認するうえでユーザー認証を要求するをご覧ください。

共有設定を編集する

次のコード スニペットは、EncryptedSharedPreferences を使用して、ユーザーの共有設定のセットをより安全に編集する方法を示しています。

Kotlin

val sharedPreferences = EncryptedSharedPreferences
    .create(
    fileName,
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

val sharedPrefsEditor = sharedPreferences.edit()

Java

EncryptedSharedPreferences sharedPreferences = EncryptedSharedPreferences
        .create(
                fileName,
                masterKeyAlias,
                context,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        );

SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();